Dismiss target v2
Current dismiss flow - On bubble drag, show gradient with "X Dismiss" - When bubbles get close to the gradient, show X-in-circle This change - Removes gradient and "X Dismiss" - Shows X-in-circle (with 70% scrim inside) on bubble drag - Reduces bubble_dismiss_encircle_size to spec (56dp => 52dp) - Removes duplicate mDismissContainer in BubbleStackView Fixes: 136199542 Test: manual (dismiss target has scrim, shows on bubble drag) Test: manual (dismiss target behaves consistently for consecutive drags) Test: atest SystemUITests Change-Id: I21101ca9f2eb1b3c53b613231557f9f7936fddfa
This commit is contained in:
@@ -24,4 +24,5 @@
|
||||
android:width="1dp"
|
||||
android:color="#66FFFFFF" />
|
||||
|
||||
<solid android:color="#B3000000" />
|
||||
</shape>
|
||||
@@ -20,6 +20,13 @@
|
||||
android:layout_height="@dimen/pip_dismiss_gradient_height"
|
||||
android:layout_gravity="bottom|center_horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bubble_dismiss_circle"
|
||||
android:layout_width="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_height="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bubble_dismiss_circle" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bubble_dismiss_icon_container"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -38,29 +45,5 @@
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/bubble_dismiss_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bubble_dismiss_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="9dp"
|
||||
android:layout_marginBottom="9dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
|
||||
android:textColor="@android:color/white"
|
||||
android:shadowColor="@android:color/black"
|
||||
android:shadowDx="-1"
|
||||
android:shadowDy="1"
|
||||
android:shadowRadius="0.01"
|
||||
android:text="@string/bubble_dismiss_text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bubble_dismiss_circle"
|
||||
android:layout_width="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_height="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_gravity="center"
|
||||
android:alpha="0"
|
||||
android:background="@drawable/bubble_dismiss_circle" />
|
||||
</FrameLayout>
|
||||
@@ -1114,7 +1114,7 @@
|
||||
<!-- Size of bubble icon bitmap. -->
|
||||
<dimen name="bubble_icon_bitmap_size">52dp</dimen>
|
||||
<!-- Size of the circle around the bubbles when they're in the dismiss target. -->
|
||||
<dimen name="bubble_dismiss_encircle_size">56dp</dimen>
|
||||
<dimen name="bubble_dismiss_encircle_size">52dp</dimen>
|
||||
<!-- How much to inset the icon in the circle -->
|
||||
<dimen name="bubble_icon_inset">16dp</dimen>
|
||||
<!-- Padding around the view displayed when the bubble is expanded -->
|
||||
|
||||
@@ -16,18 +16,13 @@
|
||||
|
||||
package com.android.systemui.bubbles;
|
||||
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.dynamicanimation.animation.DynamicAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
@@ -37,14 +32,13 @@ import com.android.systemui.R;
|
||||
|
||||
/** Dismiss view that contains a scrim gradient, as well as a dismiss icon, text, and circle. */
|
||||
public class BubbleDismissView extends FrameLayout {
|
||||
/** Duration for animations involving the dismiss target text/icon/gradient. */
|
||||
/** Duration for animations involving the dismiss target text/icon. */
|
||||
private static final int DISMISS_TARGET_ANIMATION_BASE_DURATION = 150;
|
||||
|
||||
private View mDismissGradient;
|
||||
private static final float SCALE_FOR_POP = 1.2f;
|
||||
private static final float SCALE_FOR_DISMISS = 0.9f;
|
||||
|
||||
private LinearLayout mDismissTarget;
|
||||
private ImageView mDismissIcon;
|
||||
private TextView mDismissText;
|
||||
private View mDismissCircle;
|
||||
|
||||
private SpringAnimation mDismissTargetAlphaSpring;
|
||||
@@ -54,36 +48,15 @@ public class BubbleDismissView extends FrameLayout {
|
||||
super(context);
|
||||
setVisibility(GONE);
|
||||
|
||||
mDismissGradient = new FrameLayout(mContext);
|
||||
|
||||
FrameLayout.LayoutParams gradientParams =
|
||||
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
|
||||
gradientParams.gravity = Gravity.BOTTOM;
|
||||
mDismissGradient.setLayoutParams(gradientParams);
|
||||
|
||||
Drawable gradient = mContext.getResources().getDrawable(R.drawable.pip_dismiss_scrim);
|
||||
gradient.setAlpha((int) (255 * 0.85f));
|
||||
mDismissGradient.setBackground(gradient);
|
||||
|
||||
mDismissGradient.setVisibility(GONE);
|
||||
addView(mDismissGradient);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.bubble_dismiss_target, this, true);
|
||||
mDismissTarget = findViewById(R.id.bubble_dismiss_icon_container);
|
||||
mDismissIcon = findViewById(R.id.bubble_dismiss_close_icon);
|
||||
mDismissText = findViewById(R.id.bubble_dismiss_text);
|
||||
mDismissCircle = findViewById(R.id.bubble_dismiss_circle);
|
||||
|
||||
// Set up the basic target area animations. These are very simple animations that don't need
|
||||
// fancy interpolators.
|
||||
final AccelerateDecelerateInterpolator interpolator =
|
||||
new AccelerateDecelerateInterpolator();
|
||||
mDismissGradient.animate()
|
||||
.setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
|
||||
.setInterpolator(interpolator);
|
||||
mDismissText.animate()
|
||||
.setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
|
||||
.setInterpolator(interpolator);
|
||||
mDismissIcon.animate()
|
||||
.setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION)
|
||||
.setInterpolator(interpolator);
|
||||
@@ -113,105 +86,53 @@ public class BubbleDismissView extends FrameLayout {
|
||||
});
|
||||
}
|
||||
|
||||
/** Springs in the dismiss target and fades in the gradient. */
|
||||
/** Springs in the dismiss target. */
|
||||
void springIn() {
|
||||
setVisibility(View.VISIBLE);
|
||||
|
||||
// Fade in the dismiss target (icon + text).
|
||||
// Fade in the dismiss target icon.
|
||||
mDismissIcon.animate()
|
||||
.setDuration(50)
|
||||
.scaleX(1f)
|
||||
.scaleY(1f)
|
||||
.alpha(1f);
|
||||
mDismissTarget.setAlpha(0f);
|
||||
mDismissTargetAlphaSpring.animateToFinalPosition(1f);
|
||||
|
||||
// Spring up the dismiss target (icon + text).
|
||||
// Spring up the dismiss target.
|
||||
mDismissTarget.setTranslationY(mDismissTarget.getHeight() / 2f);
|
||||
mDismissTargetVerticalSpring.animateToFinalPosition(0);
|
||||
|
||||
// Fade in the gradient.
|
||||
mDismissGradient.setVisibility(VISIBLE);
|
||||
mDismissGradient.animate().alpha(1f);
|
||||
mDismissCircle.setAlpha(0f);
|
||||
mDismissCircle.setScaleX(SCALE_FOR_POP);
|
||||
mDismissCircle.setScaleY(SCALE_FOR_POP);
|
||||
|
||||
// Make sure the dismiss elements are in the separated position (in case we hid the target
|
||||
// while they were condensed to cover the bubbles being in the target).
|
||||
mDismissIcon.setAlpha(1f);
|
||||
mDismissIcon.setScaleX(1f);
|
||||
mDismissIcon.setScaleY(1f);
|
||||
mDismissIcon.setTranslationX(0f);
|
||||
mDismissText.setAlpha(1f);
|
||||
mDismissText.setTranslationX(0f);
|
||||
// Fade in circle and reduce size.
|
||||
mDismissCircle.animate()
|
||||
.alpha(1f)
|
||||
.scaleX(1f)
|
||||
.scaleY(1f);
|
||||
}
|
||||
|
||||
/** Springs out the dismiss target and fades out the gradient. */
|
||||
/** Springs out the dismiss target. */
|
||||
void springOut() {
|
||||
// Fade out the target icon.
|
||||
mDismissIcon.animate()
|
||||
.setDuration(50)
|
||||
.scaleX(SCALE_FOR_DISMISS)
|
||||
.scaleY(SCALE_FOR_DISMISS)
|
||||
.alpha(0f);
|
||||
|
||||
// Fade out the target.
|
||||
mDismissTargetAlphaSpring.animateToFinalPosition(0f);
|
||||
|
||||
// Spring the target down a bit.
|
||||
mDismissTargetVerticalSpring.animateToFinalPosition(mDismissTarget.getHeight() / 2f);
|
||||
|
||||
// Fade out the gradient and then set it to GONE so it's not in the SBV hierarchy.
|
||||
mDismissGradient.animate().alpha(0f).withEndAction(
|
||||
() -> mDismissGradient.setVisibility(GONE));
|
||||
|
||||
// Pop out the dismiss circle.
|
||||
mDismissCircle.animate().alpha(0f).scaleX(1.2f).scaleY(1.2f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encircles the center of the dismiss target, pulling the X towards the center and hiding the
|
||||
* text.
|
||||
*/
|
||||
void animateEncircleCenterWithX(boolean encircle) {
|
||||
// Pull the text towards the center if we're encircling (it'll be faded out, leaving only
|
||||
// the X icon over the bubbles), or back to normal if we're un-encircling.
|
||||
final float textTranslation = encircle
|
||||
? -mDismissIcon.getWidth() / 4f
|
||||
: 0f;
|
||||
|
||||
// Center the icon if we're encircling, or put it back to normal if not.
|
||||
final float iconTranslation = encircle
|
||||
? mDismissTarget.getWidth() / 2f
|
||||
- mDismissIcon.getWidth() / 2f
|
||||
- mDismissIcon.getLeft()
|
||||
: 0f;
|
||||
|
||||
// Fade in/out the text and translate it.
|
||||
mDismissText.animate()
|
||||
.alpha(encircle ? 0f : 1f)
|
||||
.translationX(textTranslation);
|
||||
|
||||
mDismissIcon.animate()
|
||||
.setDuration(150)
|
||||
.translationX(iconTranslation);
|
||||
|
||||
// Fade out the gradient if we're encircling (the bubbles will 'absorb' it by darkening
|
||||
// themselves).
|
||||
mDismissGradient.animate()
|
||||
.alpha(encircle ? 0f : 1f);
|
||||
|
||||
// Prepare the circle to be 'dropped in'.
|
||||
if (encircle) {
|
||||
mDismissCircle.setAlpha(0f);
|
||||
mDismissCircle.setScaleX(1.2f);
|
||||
mDismissCircle.setScaleY(1.2f);
|
||||
}
|
||||
|
||||
// Drop in the circle, or pull it back up.
|
||||
// Pop out the circle.
|
||||
mDismissCircle.animate()
|
||||
.alpha(encircle ? 1f : 0f)
|
||||
.scaleX(encircle ? 1f : 0f)
|
||||
.scaleY(encircle ? 1f : 0f);
|
||||
}
|
||||
|
||||
/** Animates the circle and the centered icon out. */
|
||||
void animateEncirclingCircleDisappearance() {
|
||||
// Pop out the dismiss icon and circle.
|
||||
mDismissIcon.animate()
|
||||
.setDuration(50)
|
||||
.scaleX(0.9f)
|
||||
.scaleY(0.9f)
|
||||
.alpha(0f);
|
||||
mDismissCircle.animate()
|
||||
.scaleX(0.9f)
|
||||
.scaleY(0.9f)
|
||||
.scaleX(SCALE_FOR_DISMISS)
|
||||
.scaleY(SCALE_FOR_DISMISS)
|
||||
.alpha(0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -365,13 +365,6 @@ public class BubbleStackView extends FrameLayout {
|
||||
Gravity.BOTTOM));
|
||||
addView(mDismissContainer);
|
||||
|
||||
mDismissContainer = new BubbleDismissView(mContext);
|
||||
mDismissContainer.setLayoutParams(new FrameLayout.LayoutParams(
|
||||
MATCH_PARENT,
|
||||
getResources().getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height),
|
||||
Gravity.BOTTOM));
|
||||
addView(mDismissContainer);
|
||||
|
||||
mExpandedViewXAnim =
|
||||
new SpringAnimation(mExpandedViewContainer, DynamicAnimation.TRANSLATION_X);
|
||||
mExpandedViewXAnim.setSpring(
|
||||
@@ -1004,7 +997,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
}
|
||||
|
||||
mExpandedAnimationController.snapBubbleBack(bubble, velX, velY);
|
||||
springOutDismissTargetAndHideCircle();
|
||||
hideDismissTarget();
|
||||
}
|
||||
|
||||
void onDragStart() {
|
||||
@@ -1046,7 +1039,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
|
||||
mStackOnLeftOrWillBe = newStackX <= 0;
|
||||
updateBubbleShadowsAndDotPosition(true /* animate */);
|
||||
springOutDismissTargetAndHideCircle();
|
||||
hideDismissTarget();
|
||||
}
|
||||
|
||||
void onFlyoutDragStart() {
|
||||
@@ -1180,9 +1173,6 @@ public class BubbleStackView extends FrameLayout {
|
||||
|
||||
animateDesaturateAndDarken(magnetView, true);
|
||||
}
|
||||
|
||||
mDismissContainer.animateEncircleCenterWithX(true);
|
||||
|
||||
} else {
|
||||
mAnimatingMagnet = false;
|
||||
|
||||
@@ -1193,8 +1183,6 @@ public class BubbleStackView extends FrameLayout {
|
||||
mExpandedAnimationController.demagnetizeBubbleTo(x, y, velX, velY);
|
||||
animateDesaturateAndDarken(magnetView, false);
|
||||
}
|
||||
|
||||
mDismissContainer.animateEncircleCenterWithX(false);
|
||||
}
|
||||
|
||||
mVibrator.vibrate(VibrationEffect.get(toTarget
|
||||
@@ -1213,7 +1201,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
mAfterMagnet = null;
|
||||
|
||||
mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
|
||||
mDismissContainer.animateEncirclingCircleDisappearance();
|
||||
mDismissContainer.springOut();
|
||||
|
||||
// 'Implode' the stack and then hide the dismiss target.
|
||||
if (touchedView == this) {
|
||||
@@ -1251,7 +1239,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/** Animates in the dismiss target, including the gradient behind it. */
|
||||
/** Animates in the dismiss target. */
|
||||
private void springInDismissTarget() {
|
||||
if (mShowingDismiss) {
|
||||
return;
|
||||
@@ -1269,7 +1257,7 @@ public class BubbleStackView extends FrameLayout {
|
||||
* Animates the dismiss target out, as well as the circle that encircles the bubbles, if they
|
||||
* were dragged into the target and encircled.
|
||||
*/
|
||||
private void springOutDismissTargetAndHideCircle() {
|
||||
private void hideDismissTarget() {
|
||||
if (!mShowingDismiss) {
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user