Merge changes from topic "floating_dismiss" into tm-dev
* changes: Update PIP dismiss to use DismissView Update dismiss to new spec
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
<dimen name="dismiss_circle_size">96dp</dimen>
|
||||
<dimen name="dismiss_circle_small">60dp</dimen>
|
||||
|
||||
<!-- The height of the gradient indicating the dismiss edge when moving a PIP. -->
|
||||
<dimen name="floating_dismiss_gradient_height">250dp</dimen>
|
||||
<!-- The height of the gradient indicating the dismiss edge when moving a PIP or bubble. -->
|
||||
<dimen name="floating_dismiss_gradient_height">548dp</dimen>
|
||||
|
||||
<!-- The padding around a PiP actions. -->
|
||||
<dimen name="pip_action_padding">16dp</dimen>
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.wm.shell.bubbles
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
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.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.WindowInsets
|
||||
import android.widget.FrameLayout
|
||||
import androidx.dynamicanimation.animation.DynamicAnimation
|
||||
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.animation.PhysicsAnimator
|
||||
import com.android.wm.shell.common.DismissCircleView
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
|
||||
/*
|
||||
* 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 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 =
|
||||
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 {
|
||||
setLayoutParams(LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
@@ -53,8 +68,7 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
setClipToPadding(false)
|
||||
setClipChildren(false)
|
||||
setVisibility(View.INVISIBLE)
|
||||
setBackgroundResource(
|
||||
R.drawable.floating_dismiss_gradient_transition)
|
||||
setBackgroundDrawable(gradientDrawable)
|
||||
|
||||
val targetSize: Int = resources.getDimensionPixelSize(R.dimen.dismiss_circle_size)
|
||||
addView(circle, LayoutParams(targetSize, targetSize,
|
||||
@@ -71,7 +85,11 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
if (isShowing) return
|
||||
isShowing = true
|
||||
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
|
||||
.spring(DynamicAnimation.TRANSLATION_Y, 0f, spring)
|
||||
@@ -85,7 +103,10 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
fun hide() {
|
||||
if (!isShowing) return
|
||||
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
|
||||
.spring(DynamicAnimation.TRANSLATION_Y, height.toFloat(),
|
||||
spring)
|
||||
@@ -93,6 +114,13 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
.start()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the animator for the dismiss target.
|
||||
*/
|
||||
fun cancelAnimators() {
|
||||
animator.cancel()
|
||||
}
|
||||
|
||||
fun updateResources() {
|
||||
updatePadding()
|
||||
layoutParams.height = resources.getDimensionPixelSize(
|
||||
@@ -104,6 +132,20 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
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() {
|
||||
val insets: WindowInsets = wm.getCurrentWindowMetrics().getWindowInsets()
|
||||
val navInset = insets.getInsetsIgnoringVisibility(
|
||||
|
||||
@@ -20,27 +20,20 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
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.animation.PhysicsAnimator;
|
||||
import com.android.wm.shell.bubbles.DismissView;
|
||||
import com.android.wm.shell.common.DismissCircleView;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
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 */
|
||||
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
|
||||
* 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
|
||||
* translation rather than within the WindowManager via slow layout animations.
|
||||
*/
|
||||
private ViewGroup mTargetViewContainer;
|
||||
private DismissView mTargetViewContainer;
|
||||
|
||||
/** Circle view used to render the dismiss target. */
|
||||
private DismissCircleView mTargetView;
|
||||
@@ -79,16 +69,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
*/
|
||||
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
|
||||
private boolean mEnableDismissDragToEdge;
|
||||
|
||||
@@ -125,12 +105,8 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
cleanUpDismissTarget();
|
||||
}
|
||||
|
||||
mTargetView = new DismissCircleView(mContext);
|
||||
mTargetViewContainer = new FrameLayout(mContext);
|
||||
mTargetViewContainer.setBackgroundDrawable(
|
||||
mContext.getDrawable(R.drawable.floating_dismiss_gradient_transition));
|
||||
mTargetViewContainer.setClipChildren(false);
|
||||
mTargetViewContainer.addView(mTargetView);
|
||||
mTargetViewContainer = new DismissView(mContext);
|
||||
mTargetView = mTargetViewContainer.getCircle();
|
||||
mTargetViewContainer.setOnApplyWindowInsetsListener((view, windowInsets) -> {
|
||||
if (!windowInsets.equals(mWindowInsets)) {
|
||||
mWindowInsets = windowInsets;
|
||||
@@ -187,7 +163,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
}
|
||||
});
|
||||
|
||||
mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -213,19 +188,13 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
if (mTargetView == null) {
|
||||
return;
|
||||
}
|
||||
if (mTargetViewContainer != null) {
|
||||
mTargetViewContainer.updateResources();
|
||||
}
|
||||
|
||||
final Resources res = mContext.getResources();
|
||||
mTargetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
|
||||
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
|
||||
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. */
|
||||
public void createOrUpdateDismissTarget() {
|
||||
if (!mTargetViewContainer.isAttachedToWindow()) {
|
||||
mMagneticTargetAnimator.cancel();
|
||||
mTargetViewContainer.cancelAnimators();
|
||||
|
||||
mTargetViewContainer.setVisibility(View.INVISIBLE);
|
||||
mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
@@ -312,18 +281,8 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
createOrUpdateDismissTarget();
|
||||
|
||||
if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
|
||||
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
|
||||
mTargetViewContainer.setVisibility(View.VISIBLE);
|
||||
mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this);
|
||||
|
||||
// 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);
|
||||
mTargetViewContainer.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,16 +291,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
|
||||
if (!mEnableDismissDragToEdge) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMagneticTargetAnimator
|
||||
.spring(DynamicAnimation.TRANSLATION_Y,
|
||||
mTargetViewContainer.getHeight(),
|
||||
mTargetSpringConfig)
|
||||
.withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
|
||||
.start();
|
||||
|
||||
((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
|
||||
DISMISS_TRANSITION_DURATION_MS);
|
||||
mTargetViewContainer.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user