Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dd850f4 authored by Miranda Kephart's avatar Miranda Kephart
Browse files

Use ConstraintLayout for screenshot UI

There are some problems with the screenshot UI layout, especially
in RTL (where the dismiss button disappears). Using constraints
rather than setting the position of the button directly fixes this
problem, and should make updates to the appearance of the UI in
landscape simpler.

Bug: 151814483
Fix: 151814483
Test: manual -- made sure that the animation and final UI state
looked correct in both LTR and RTL layouts

Change-Id: Ia8d21c028279bc6b70a1b338bea979f2ce2808bc
parent 6fc746b5
Loading
Loading
Loading
Loading
+58 −30
Original line number Diff line number Diff line
@@ -14,60 +14,89 @@
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/global_screenshot_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/global_screenshot_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@android:color/black"
        android:visibility="gone"/>
    <ImageView
        android:id="@+id/global_screenshot_actions_background"
        android:layout_height="400dp"
        android:layout_height="@dimen/global_screenshot_bg_protection_height"
        android:layout_width="match_parent"
        android:layout_gravity="bottom|center"
        android:alpha="0.0"
        android:src="@drawable/screenshot_actions_background_protection"
        android:alpha="0"/>
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <ImageView
        android:id="@+id/global_screenshot_actions_container_background"
        android:visibility="gone"
        android:layout_height="0dp"
        android:layout_width="0dp"
        android:elevation="1dp"
        android:background="@drawable/action_chip_container_background"
        android:layout_marginStart="@dimen/screenshot_action_container_margin_horizontal"
        app:layout_constraintBottom_toBottomOf="@+id/global_screenshot_actions_container"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/global_screenshot_actions_container"
        app:layout_constraintEnd_toEndOf="@+id/global_screenshot_actions_container"/>
    <HorizontalScrollView
        android:id="@+id/global_screenshot_actions_container"
        android:layout_width="wrap_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|left"
        android:elevation="1dp"
        android:fillViewport="true"
        android:layout_marginHorizontal="@dimen/screenshot_action_container_margin_horizontal"
        android:layout_marginEnd="@dimen/screenshot_action_container_margin_horizontal"
        android:layout_marginBottom="@dimen/screenshot_action_container_offset_y"
        android:gravity="center"
        android:paddingLeft="@dimen/screenshot_action_container_padding_left"
        android:paddingRight="@dimen/screenshot_action_container_padding_right"
        android:paddingHorizontal="@dimen/screenshot_action_container_padding_right"
        android:paddingVertical="@dimen/screenshot_action_container_padding_vertical"
        android:visibility="gone"
        android:elevation="1dp"
        android:scrollbars="none"
        android:background="@drawable/action_chip_container_background">
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintWidth_percent="1.0"
        app:layout_constraintWidth_max="wrap"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview"
        app:layout_constraintEnd_toEndOf="parent">
        <LinearLayout
            android:id="@+id/global_screenshot_actions"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </HorizontalScrollView>
    <ImageView
        android:id="@+id/global_screenshot"
        android:layout_width="wrap_content"
        android:id="@+id/global_screenshot_animated_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:visibility="gone"
        android:elevation="@dimen/screenshot_preview_elevation"
        android:background="@drawable/screenshot_rounded_corners"
        android:adjustViewBounds="true"/>
    <ImageView
        android:id="@+id/global_screenshot_preview"
        android:layout_width="@dimen/global_screenshot_x_scale"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginStart="@dimen/screenshot_offset_x"
        android:layout_marginBottom="@dimen/screenshot_offset_y"
        android:scaleType="fitEnd"
        android:elevation="@dimen/screenshot_preview_elevation"
        android:visibility="gone"
        android:background="@drawable/screenshot_rounded_corners"
        android:adjustViewBounds="true"
        android:contentDescription="@string/screenshot_preview_description"/>
        android:contentDescription="@string/screenshot_preview_description"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>
    <FrameLayout
        android:id="@+id/global_screenshot_dismiss_button"
        android:layout_width="@dimen/screenshot_dismiss_button_tappable_size"
        android:layout_height="@dimen/screenshot_dismiss_button_tappable_size"
        android:elevation="7dp"
        android:visibility="gone"
        android:contentDescription="@string/screenshot_dismiss_ui_description">
        android:contentDescription="@string/screenshot_dismiss_ui_description"
        app:layout_constraintStart_toEndOf="@+id/global_screenshot_preview"
        app:layout_constraintEnd_toEndOf="@+id/global_screenshot_preview"
        app:layout_constraintTop_toTopOf="@+id/global_screenshot_preview"
        app:layout_constraintBottom_toTopOf="@+id/global_screenshot_preview">
        <ImageView
            android:id="@+id/global_screenshot_dismiss_image"
            android:layout_width="match_parent"
@@ -79,14 +108,13 @@
        android:id="@+id/global_screenshot_flash"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@android:color/white"
        android:visibility="gone"
        android:elevation="@dimen/screenshot_preview_elevation"
        android:visibility="gone"/>
        android:src="@android:color/white"/>
    <com.android.systemui.screenshot.ScreenshotSelectorView
        android:id="@+id/global_screenshot_selector"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        android:pointerIcon="crosshair"/>

</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
+2 −2
Original line number Diff line number Diff line
@@ -19,11 +19,11 @@
    android:id="@+id/global_screenshot_action_chip"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="@dimen/screenshot_action_chip_margin_right"
    android:layout_marginEnd="@dimen/screenshot_action_chip_margin_right"
    android:layout_gravity="center"
    android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
    android:background="@drawable/action_chip_background"
    android:alpha="0"
    android:alpha="0.0"
    android:gravity="center">
    <ImageView
        android:id="@+id/screenshot_action_chip_icon"
+1 −0
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@
    <!-- The padding on the global screenshot background image -->
    <dimen name="global_screenshot_legacy_bg_padding">20dp</dimen>
    <dimen name="global_screenshot_bg_padding">20dp</dimen>
    <dimen name="global_screenshot_bg_protection_height">400dp</dimen>
    <dimen name="global_screenshot_x_scale">80dp</dimen>
    <dimen name="screenshot_preview_elevation">6dp</dimen>
    <dimen name="screenshot_offset_y">48dp</dimen>
+93 −60
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.screenshot;

import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_SCROLLING_ENABLED;
@@ -72,7 +71,6 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
@@ -187,10 +185,11 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset

    private final View mScreenshotLayout;
    private final ScreenshotSelectorView mScreenshotSelectorView;
    private final ImageView mBackgroundView;
    private final ImageView mScreenshotView;
    private final ImageView mScreenshotAnimatedView;
    private final ImageView mScreenshotPreview;
    private final ImageView mScreenshotFlash;
    private final HorizontalScrollView mActionsContainer;
    private final ImageView mActionsContainerBackground;
    private final FrameLayout mActionsContainer;
    private final LinearLayout mActionsView;
    private final ImageView mBackgroundProtection;
    private final FrameLayout mDismissButton;
@@ -205,8 +204,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset

    private float mScreenshotOffsetXPx;
    private float mScreenshotOffsetYPx;
    private float mScreenshotHeightPx;
    private float mDismissButtonSize;
    private float mCornerSizeX;
    private float mDismissDeltaY;

@@ -244,10 +241,19 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset

        // Inflate the screenshot layout
        mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
        mBackgroundView = mScreenshotLayout.findViewById(R.id.global_screenshot_background);
        mScreenshotView = mScreenshotLayout.findViewById(R.id.global_screenshot);
        mScreenshotView.setClipToOutline(true);
        mScreenshotView.setOutlineProvider(new ViewOutlineProvider() {
        mScreenshotAnimatedView =
                mScreenshotLayout.findViewById(R.id.global_screenshot_animated_view);
        mScreenshotAnimatedView.setClipToOutline(true);
        mScreenshotAnimatedView.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
                        ROUNDED_CORNER_RADIUS * view.getWidth());
            }
        });
        mScreenshotPreview = mScreenshotLayout.findViewById(R.id.global_screenshot_preview);
        mScreenshotPreview.setClipToOutline(true);
        mScreenshotPreview.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setRoundRect(new Rect(0, 0, view.getWidth(), view.getHeight()),
@@ -255,6 +261,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
            }
        });

        mActionsContainerBackground = mScreenshotLayout.findViewById(
                R.id.global_screenshot_actions_container_background);
        mActionsContainer = mScreenshotLayout.findViewById(
                R.id.global_screenshot_actions_container);
        mActionsView = mScreenshotLayout.findViewById(R.id.global_screenshot_actions);
@@ -273,9 +281,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
        mScreenshotLayout.setFocusable(true);
        mScreenshotSelectorView.setFocusable(true);
        mScreenshotSelectorView.setFocusableInTouchMode(true);
        mScreenshotView.setPivotX(0);
        mScreenshotView.setPivotY(0);
        mActionsContainer.setPivotX(0);
        mScreenshotAnimatedView.setPivotX(0);
        mScreenshotAnimatedView.setPivotY(0);

        // Setup the window that we are going to use
        mWindowLayoutParams = new WindowManager.LayoutParams(
@@ -297,10 +304,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset

        mScreenshotOffsetXPx = resources.getDimensionPixelSize(R.dimen.screenshot_offset_x);
        mScreenshotOffsetYPx = resources.getDimensionPixelSize(R.dimen.screenshot_offset_y);
        mScreenshotHeightPx =
                resources.getDimensionPixelSize(R.dimen.screenshot_action_container_offset_y);
        mDismissButtonSize = resources.getDimensionPixelSize(
                R.dimen.screenshot_dismiss_button_tappable_size);
        mCornerSizeX = resources.getDimensionPixelSize(R.dimen.global_screenshot_x_scale);
        mDismissDeltaY = resources.getDimensionPixelSize(R.dimen.screenshot_dismissal_height_delta);

@@ -318,7 +321,7 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
        Region touchRegion = new Region();

        Rect screenshotRect = new Rect();
        mScreenshotView.getBoundsOnScreen(screenshotRect);
        mScreenshotPreview.getBoundsOnScreen(screenshotRect);
        touchRegion.op(screenshotRect, Region.Op.UNION);
        Rect actionsRect = new Rect();
        mActionsContainer.getBoundsOnScreen(actionsRect);
@@ -469,6 +472,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
     */
    private void dismissScreenshot(String reason, boolean immediate) {
        Log.v(TAG, "clearing screenshot: " + reason);
        mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
        mScreenshotLayout.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
        if (!immediate) {
            mDismissAnimation = createScreenshotDismissAnimation();
            mDismissAnimation.addListener(new AnimatorListenerAdapter() {
@@ -488,23 +493,23 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
        if (mScreenshotLayout.isAttachedToWindow()) {
            mWindowManager.removeView(mScreenshotLayout);
        }
        mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
        mScreenshotLayout.getViewTreeObserver().removeOnComputeInternalInsetsListener(this);

        // Clear any references to the bitmap
        mScreenshotView.setImageBitmap(null);
        mScreenshotPreview.setImageBitmap(null);
        mScreenshotAnimatedView.setImageBitmap(null);
        mActionsContainerBackground.setVisibility(View.GONE);
        mActionsContainer.setVisibility(View.GONE);
        mBackgroundView.setVisibility(View.GONE);
        mBackgroundProtection.setAlpha(0f);
        mDismissButton.setVisibility(View.GONE);
        mScreenshotView.setVisibility(View.GONE);
        mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
        mScreenshotView.setContentDescription(
        mScreenshotPreview.setVisibility(View.GONE);
        mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
        mScreenshotPreview.setContentDescription(
                mContext.getResources().getString(R.string.screenshot_preview_description));
        mScreenshotLayout.setAlpha(1);
        mDismissButton.setTranslationY(0);
        mActionsContainer.setTranslationY(0);
        mScreenshotView.setTranslationY(0);
        mActionsContainerBackground.setTranslationY(0);
        mScreenshotPreview.setTranslationY(0);
    }

    /**
@@ -514,9 +519,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
     */
    private void reloadAssets() {
        mDismissImage.setImageDrawable(mContext.getDrawable(R.drawable.screenshot_cancel));
        mActionsContainer.setBackground(
        mActionsContainerBackground.setBackground(
                mContext.getDrawable(R.drawable.action_chip_container_background));

    }

    /**
@@ -558,10 +562,6 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
                    Toast.LENGTH_SHORT).show();
        }


        // Add the view for the animation
        mScreenshotView.setImageBitmap(mScreenBitmap);

        mScreenshotAnimation = createScreenshotDropInAnimation(w, h, screenRect);

        saveScreenshotInWorkerThread(finisher, new ActionsReadyListener() {
@@ -600,8 +600,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
            // Play the shutter sound to notify that we've taken a screenshot
            mCameraSound.play(MediaActionSound.SHUTTER_CLICK);

            mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mScreenshotView.buildLayer();
            mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mScreenshotPreview.buildLayer();
            mScreenshotAnimation.start();
        });
    }
@@ -609,6 +609,14 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
    private AnimatorSet createScreenshotDropInAnimation(int width, int height, Rect bounds) {
        float cornerScale = mCornerSizeX / (float) width;

        mScreenshotAnimatedView.setScaleX(1);
        mScreenshotAnimatedView.setScaleY(1);
        mScreenshotAnimatedView.setX(0);
        mScreenshotAnimatedView.setY(0);

        mScreenshotAnimatedView.setImageBitmap(mScreenBitmap);
        mScreenshotPreview.setImageBitmap(mScreenBitmap);

        AnimatorSet dropInAnimation = new AnimatorSet();
        ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
        flashInAnimator.setDuration(SCREENSHOT_FLASH_IN_DURATION_MS);
@@ -623,9 +631,16 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
                mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));

        final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
        final PointF finalPos = new PointF(mScreenshotOffsetXPx + width * cornerScale / 2f,
                mDisplayMetrics.heightPixels - mScreenshotOffsetYPx
                        - height * cornerScale / 2f);
        float finalX;
        if (mContext.getResources().getConfiguration().getLayoutDirection()
                == View.LAYOUT_DIRECTION_LTR) {
            finalX = mScreenshotOffsetXPx + width * cornerScale / 2f;
        } else {
            finalX = width - mScreenshotOffsetXPx - width * cornerScale / 2f;
        }
        float finalY =
                mDisplayMetrics.heightPixels - mScreenshotOffsetYPx - height * cornerScale / 2f;
        final PointF finalPos = new PointF(finalX, finalY);

        ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
        toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
@@ -639,30 +654,33 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
            if (t < scalePct) {
                float scale = MathUtils.lerp(
                        1, cornerScale, mFastOutSlowIn.getInterpolation(t / scalePct));
                mScreenshotView.setScaleX(scale);
                mScreenshotView.setScaleY(scale);
                mScreenshotAnimatedView.setScaleX(scale);
                mScreenshotAnimatedView.setScaleY(scale);
            } else {
                mScreenshotView.setScaleX(cornerScale);
                mScreenshotView.setScaleY(cornerScale);
                mScreenshotAnimatedView.setScaleX(cornerScale);
                mScreenshotAnimatedView.setScaleY(cornerScale);
            }

            float currentScaleX = mScreenshotAnimatedView.getScaleX();
            float currentScaleY = mScreenshotAnimatedView.getScaleY();

            if (t < xPositionPct) {
                float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
                        mFastOutSlowIn.getInterpolation(t / xPositionPct));
                mScreenshotView.setX(xCenter - width * mScreenshotView.getScaleX() / 2f);
                mScreenshotAnimatedView.setX(xCenter - width * currentScaleX / 2f);
            } else {
                mScreenshotView.setX(finalPos.x - width * mScreenshotView.getScaleX() / 2f);
                mScreenshotAnimatedView.setX(finalPos.x - width * currentScaleX / 2f);
            }
            float yCenter = MathUtils.lerp(startPos.y, finalPos.y,
                    mFastOutSlowIn.getInterpolation(t));
            mScreenshotView.setY(yCenter - height * mScreenshotView.getScaleY() / 2f);
            mScreenshotAnimatedView.setY(yCenter - height * currentScaleY / 2f);
        });

        toCorner.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                mScreenshotView.setVisibility(View.VISIBLE);
                mScreenshotAnimatedView.setVisibility(View.VISIBLE);
            }
        });

@@ -676,15 +694,16 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mScreenshotView.setScaleX(cornerScale);
                mScreenshotView.setScaleY(cornerScale);
                mScreenshotView.setX(finalPos.x - width * cornerScale / 2f);
                mScreenshotView.setY(finalPos.y - height * cornerScale / 2f);
                mScreenshotAnimatedView.setScaleX(1);
                mScreenshotAnimatedView.setScaleY(1);
                mScreenshotAnimatedView.setX(finalPos.x - width * cornerScale / 2f);
                mScreenshotAnimatedView.setY(finalPos.y - height * cornerScale / 2f);
                Rect bounds = new Rect();
                mScreenshotView.getBoundsOnScreen(bounds);
                mDismissButton.setX(bounds.right - mDismissButtonSize / 2f);
                mDismissButton.setY(bounds.top - mDismissButtonSize / 2f);
                mDismissButton.getBoundsOnScreen(bounds);
                mScreenshotAnimatedView.setVisibility(View.GONE);
                mScreenshotPreview.setVisibility(View.VISIBLE);
                mDismissButton.setVisibility(View.VISIBLE);
                mScreenshotLayout.forceLayout();
            }
        });

@@ -747,7 +766,7 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
        mActionsView.addView(editChip);
        chips.add(editChip);

        mScreenshotView.setOnClickListener(v -> {
        mScreenshotPreview.setOnClickListener(v -> {
            try {
                imageData.editAction.actionIntent.send();
                mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED);
@@ -757,7 +776,7 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
                Log.e(TAG, "Intent cancelled", e);
            }
        });
        mScreenshotView.setContentDescription(imageData.editAction.title);
        mScreenshotPreview.setContentDescription(imageData.editAction.title);

        if (DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, SCREENSHOT_SCROLLING_ENABLED, false)) {
            ScreenshotActionChip scrollChip = (ScreenshotActionChip) inflater.inflate(
@@ -775,20 +794,33 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
            chips.add(scrollChip);
        }

        // remove the margin from the last chip so that it's correctly aligned with the end
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)
                mActionsView.getChildAt(mActionsView.getChildCount() - 1).getLayoutParams();
        params.setMarginEnd(0);

        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS);
        float alphaFraction = (float) SCREENSHOT_ACTIONS_ALPHA_DURATION_MS
                / SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS;
        mActionsContainer.setVisibility(VISIBLE);
        mActionsContainer.setAlpha(0);
        mActionsContainer.setVisibility(View.VISIBLE);
        mActionsContainer.setAlpha(0f);
        mActionsContainerBackground.setAlpha(0f);
        mActionsContainerBackground.setVisibility(View.VISIBLE);

        mActionsContainer.setPivotX(0);
        mActionsContainerBackground.setPivotX(0);

        animator.addUpdateListener(animation -> {
            float t = animation.getAnimatedFraction();
            mBackgroundProtection.setAlpha(t);
            mActionsContainer.setAlpha(t < alphaFraction ? t / alphaFraction : 1);
            float containerAlpha = t < alphaFraction ? t / alphaFraction : 1;
            mActionsContainer.setAlpha(containerAlpha);
            mActionsContainerBackground.setAlpha(containerAlpha);
            float containerScale = SCREENSHOT_ACTIONS_START_SCALE_X
                    + (t * (1 - SCREENSHOT_ACTIONS_START_SCALE_X));
            mActionsContainer.setScaleX(containerScale);
            mActionsContainerBackground.setScaleX(containerScale);
            for (ScreenshotActionChip chip : chips) {
                chip.setAlpha(t);
                chip.setScaleX(1 / containerScale); // invert to keep size of children constant
@@ -808,13 +840,14 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
        ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1);
        yAnim.setInterpolator(mAccelerateInterpolator);
        yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS);
        float screenshotStartY = mScreenshotView.getTranslationY();
        float screenshotStartY = mScreenshotPreview.getTranslationY();
        float dismissStartY = mDismissButton.getTranslationY();
        yAnim.addUpdateListener(animation -> {
            float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
            mScreenshotView.setTranslationY(screenshotStartY + yDelta);
            mScreenshotPreview.setTranslationY(screenshotStartY + yDelta);
            mDismissButton.setTranslationY(dismissStartY + yDelta);
            mActionsContainer.setTranslationY(yDelta);
            mActionsContainerBackground.setTranslationY(yDelta);
        });

        AnimatorSet animSet = new AnimatorSet();