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

Commit ba688138 authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge changes from topic "floating_dismiss" into tm-dev

* changes:
  Update PIP dismiss to use DismissView
  Update dismiss to new spec
parents 014c2596 a62aa184
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -18,8 +18,8 @@
    <dimen name="dismiss_circle_size">96dp</dimen>
    <dimen name="dismiss_circle_size">96dp</dimen>
    <dimen name="dismiss_circle_small">60dp</dimen>
    <dimen name="dismiss_circle_small">60dp</dimen>


    <!-- The height of the gradient indicating the dismiss edge when moving a PIP. -->
    <!-- The height of the gradient indicating the dismiss edge when moving a PIP or bubble. -->
    <dimen name="floating_dismiss_gradient_height">250dp</dimen>
    <dimen name="floating_dismiss_gradient_height">548dp</dimen>


    <!-- The padding around a PiP actions. -->
    <!-- The padding around a PiP actions. -->
    <dimen name="pip_action_padding">16dp</dimen>
    <dimen name="pip_action_padding">16dp</dimen>
+50 −8
Original line number Original line Diff line number Diff line
@@ -16,11 +16,16 @@


package com.android.wm.shell.bubbles
package com.android.wm.shell.bubbles


import android.animation.ObjectAnimator
import android.content.Context
import android.content.Context
import android.graphics.drawable.TransitionDrawable
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.util.IntProperty
import android.view.Gravity
import android.view.Gravity
import android.view.View
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup
import android.view.WindowManager
import android.view.WindowInsets
import android.widget.FrameLayout
import android.widget.FrameLayout
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY
import androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY
@@ -28,8 +33,6 @@ import androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW
import com.android.wm.shell.R
import com.android.wm.shell.R
import com.android.wm.shell.animation.PhysicsAnimator
import com.android.wm.shell.animation.PhysicsAnimator
import com.android.wm.shell.common.DismissCircleView
import com.android.wm.shell.common.DismissCircleView
import android.view.WindowInsets
import android.view.WindowManager


/*
/*
 * View that handles interactions between DismissCircleView and BubbleStackView.
 * View that handles interactions between DismissCircleView and BubbleStackView.
@@ -41,9 +44,21 @@ class DismissView(context: Context) : FrameLayout(context) {


    private val animator = PhysicsAnimator.getInstance(circle)
    private val animator = PhysicsAnimator.getInstance(circle)
    private val spring = PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY)
    private val spring = PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY)
    private val DISMISS_SCRIM_FADE_MS = 200
    private val DISMISS_SCRIM_FADE_MS = 200L
    private var wm: WindowManager =
    private var wm: WindowManager =
            context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    private var gradientDrawable = createGradient()

    private val GRADIENT_ALPHA: IntProperty<GradientDrawable> =
            object : IntProperty<GradientDrawable>("alpha") {
        override fun setValue(d: GradientDrawable, percent: Int) {
            d.alpha = percent
        }
        override fun get(d: GradientDrawable): Int {
            return d.alpha
        }
    }

    init {
    init {
        setLayoutParams(LayoutParams(
        setLayoutParams(LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT,
@@ -53,8 +68,7 @@ class DismissView(context: Context) : FrameLayout(context) {
        setClipToPadding(false)
        setClipToPadding(false)
        setClipChildren(false)
        setClipChildren(false)
        setVisibility(View.INVISIBLE)
        setVisibility(View.INVISIBLE)
        setBackgroundResource(
        setBackgroundDrawable(gradientDrawable)
            R.drawable.floating_dismiss_gradient_transition)


        val targetSize: Int = resources.getDimensionPixelSize(R.dimen.dismiss_circle_size)
        val targetSize: Int = resources.getDimensionPixelSize(R.dimen.dismiss_circle_size)
        addView(circle, LayoutParams(targetSize, targetSize,
        addView(circle, LayoutParams(targetSize, targetSize,
@@ -71,7 +85,11 @@ class DismissView(context: Context) : FrameLayout(context) {
        if (isShowing) return
        if (isShowing) return
        isShowing = true
        isShowing = true
        setVisibility(View.VISIBLE)
        setVisibility(View.VISIBLE)
        (getBackground() as TransitionDrawable).startTransition(DISMISS_SCRIM_FADE_MS)
        val alphaAnim = ObjectAnimator.ofInt(gradientDrawable, GRADIENT_ALPHA,
                gradientDrawable.alpha, 255)
        alphaAnim.setDuration(DISMISS_SCRIM_FADE_MS)
        alphaAnim.start()

        animator.cancel()
        animator.cancel()
        animator
        animator
            .spring(DynamicAnimation.TRANSLATION_Y, 0f, spring)
            .spring(DynamicAnimation.TRANSLATION_Y, 0f, spring)
@@ -85,7 +103,10 @@ class DismissView(context: Context) : FrameLayout(context) {
    fun hide() {
    fun hide() {
        if (!isShowing) return
        if (!isShowing) return
        isShowing = false
        isShowing = false
        (getBackground() as TransitionDrawable).reverseTransition(DISMISS_SCRIM_FADE_MS)
        val alphaAnim = ObjectAnimator.ofInt(gradientDrawable, GRADIENT_ALPHA,
                gradientDrawable.alpha, 0)
        alphaAnim.setDuration(DISMISS_SCRIM_FADE_MS)
        alphaAnim.start()
        animator
        animator
            .spring(DynamicAnimation.TRANSLATION_Y, height.toFloat(),
            .spring(DynamicAnimation.TRANSLATION_Y, height.toFloat(),
                spring)
                spring)
@@ -93,6 +114,13 @@ class DismissView(context: Context) : FrameLayout(context) {
            .start()
            .start()
    }
    }


    /**
     * Cancels the animator for the dismiss target.
     */
    fun cancelAnimators() {
        animator.cancel()
    }

    fun updateResources() {
    fun updateResources() {
        updatePadding()
        updatePadding()
        layoutParams.height = resources.getDimensionPixelSize(
        layoutParams.height = resources.getDimensionPixelSize(
@@ -104,6 +132,20 @@ class DismissView(context: Context) : FrameLayout(context) {
        circle.requestLayout()
        circle.requestLayout()
    }
    }


    private fun createGradient(): GradientDrawable {
        val gradientColor = context.resources.getColor(android.R.color.system_neutral1_900)
        val alpha = 0.7f * 255
        val gradientColorWithAlpha = Color.argb(alpha.toInt(),
                Color.red(gradientColor),
                Color.green(gradientColor),
                Color.blue(gradientColor))
        val gd = GradientDrawable(
                GradientDrawable.Orientation.BOTTOM_TOP,
                intArrayOf(gradientColorWithAlpha, Color.TRANSPARENT))
        gd.setAlpha(0)
        return gd
    }

    private fun updatePadding() {
    private fun updatePadding() {
        val insets: WindowInsets = wm.getCurrentWindowMetrics().getWindowInsets()
        val insets: WindowInsets = wm.getCurrentWindowMetrics().getWindowInsets()
        val navInset = insets.getInsetsIgnoringVisibility(
        val navInset = insets.getInsetsIgnoringVisibility(
+10 −60
Original line number Original line Diff line number Diff line
@@ -20,27 +20,20 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M


import android.content.Context;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.drawable.TransitionDrawable;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager;
import android.widget.FrameLayout;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;


import com.android.wm.shell.R;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.bubbles.DismissView;
import com.android.wm.shell.common.DismissCircleView;
import com.android.wm.shell.common.DismissCircleView;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
@@ -56,9 +49,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
    /* The multiplier to apply scale the target size by when applying the magnetic field radius */
    /* The multiplier to apply scale the target size by when applying the magnetic field radius */
    private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
    private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;


    /** Duration of the dismiss scrim fading in/out. */
    private static final int DISMISS_TRANSITION_DURATION_MS = 200;

    /**
    /**
     * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
     * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
     * PIP.
     * PIP.
@@ -69,7 +59,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
     * Container for the dismiss circle, so that it can be animated within the container via
     * Container for the dismiss circle, so that it can be animated within the container via
     * translation rather than within the WindowManager via slow layout animations.
     * translation rather than within the WindowManager via slow layout animations.
     */
     */
    private ViewGroup mTargetViewContainer;
    private DismissView mTargetViewContainer;


    /** Circle view used to render the dismiss target. */
    /** Circle view used to render the dismiss target. */
    private DismissCircleView mTargetView;
    private DismissCircleView mTargetView;
@@ -79,16 +69,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
     */
     */
    private MagnetizedObject.MagneticTarget mMagneticTarget;
    private MagnetizedObject.MagneticTarget mMagneticTarget;


    /**
     * PhysicsAnimator instance for animating the dismiss target in/out.
     */
    private PhysicsAnimator<View> mMagneticTargetAnimator;

    /** Default configuration to use for springing the dismiss target in/out. */
    private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
            new PhysicsAnimator.SpringConfig(
                    SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);

    // Allow dragging the PIP to a location to close it
    // Allow dragging the PIP to a location to close it
    private boolean mEnableDismissDragToEdge;
    private boolean mEnableDismissDragToEdge;


@@ -125,12 +105,8 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
            cleanUpDismissTarget();
            cleanUpDismissTarget();
        }
        }


        mTargetView = new DismissCircleView(mContext);
        mTargetViewContainer = new DismissView(mContext);
        mTargetViewContainer = new FrameLayout(mContext);
        mTargetView = mTargetViewContainer.getCircle();
        mTargetViewContainer.setBackgroundDrawable(
                mContext.getDrawable(R.drawable.floating_dismiss_gradient_transition));
        mTargetViewContainer.setClipChildren(false);
        mTargetViewContainer.addView(mTargetView);
        mTargetViewContainer.setOnApplyWindowInsetsListener((view, windowInsets) -> {
        mTargetViewContainer.setOnApplyWindowInsetsListener((view, windowInsets) -> {
            if (!windowInsets.equals(mWindowInsets)) {
            if (!windowInsets.equals(mWindowInsets)) {
                mWindowInsets = windowInsets;
                mWindowInsets = windowInsets;
@@ -187,7 +163,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
            }
            }
        });
        });


        mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
    }
    }


    @Override
    @Override
@@ -213,19 +188,13 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
        if (mTargetView == null) {
        if (mTargetView == null) {
            return;
            return;
        }
        }
        if (mTargetViewContainer != null) {
            mTargetViewContainer.updateResources();
        }


        final Resources res = mContext.getResources();
        final Resources res = mContext.getResources();
        mTargetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
        mTargetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
        final WindowInsets insets = mWindowManager.getCurrentWindowMetrics().getWindowInsets();
        final Insets navInset = insets.getInsetsIgnoringVisibility(
                WindowInsets.Type.navigationBars());
        final FrameLayout.LayoutParams newParams =
                new FrameLayout.LayoutParams(mTargetSize, mTargetSize);
        newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
        newParams.bottomMargin = navInset.bottom + mContext.getResources().getDimensionPixelSize(
                R.dimen.floating_dismiss_bottom_margin);
        mTargetView.setLayoutParams(newParams);


        // Set the magnetic field radius equal to the target size from the center of the target
        // Set the magnetic field radius equal to the target size from the center of the target
        setMagneticFieldRadiusPercent(mMagneticFieldRadiusPercent);
        setMagneticFieldRadiusPercent(mMagneticFieldRadiusPercent);
@@ -261,7 +230,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
    /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
    /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
    public void createOrUpdateDismissTarget() {
    public void createOrUpdateDismissTarget() {
        if (!mTargetViewContainer.isAttachedToWindow()) {
        if (!mTargetViewContainer.isAttachedToWindow()) {
            mMagneticTargetAnimator.cancel();
            mTargetViewContainer.cancelAnimators();


            mTargetViewContainer.setVisibility(View.INVISIBLE);
            mTargetViewContainer.setVisibility(View.INVISIBLE);
            mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
            mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
@@ -312,18 +281,8 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
        createOrUpdateDismissTarget();
        createOrUpdateDismissTarget();


        if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
        if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
            mTargetView.setTranslationY(mTargetViewContainer.getHeight());
            mTargetViewContainer.setVisibility(View.VISIBLE);
            mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this);
            mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this);

            mTargetViewContainer.show();
            // Cancel in case we were in the middle of animating it out.
            mMagneticTargetAnimator.cancel();
            mMagneticTargetAnimator
                    .spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
                    .start();

            ((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
                    DISMISS_TRANSITION_DURATION_MS);
        }
        }
    }
    }


@@ -332,16 +291,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
        if (!mEnableDismissDragToEdge) {
        if (!mEnableDismissDragToEdge) {
            return;
            return;
        }
        }

        mTargetViewContainer.hide();
        mMagneticTargetAnimator
                .spring(DynamicAnimation.TRANSLATION_Y,
                        mTargetViewContainer.getHeight(),
                        mTargetSpringConfig)
                .withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
                .start();

        ((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
                DISMISS_TRANSITION_DURATION_MS);
    }
    }


    /**
    /**