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_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>
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user