Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleDismissView.javadeleted 100644 → 0 +0 −148 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.content.Context; 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 androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; 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. */ private static final int DISMISS_TARGET_ANIMATION_BASE_DURATION = 150; 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 View mDismissCircle; private SpringAnimation mDismissTargetAlphaSpring; private SpringAnimation mDismissTargetVerticalSpring; public BubbleDismissView(Context context) { super(context); setVisibility(GONE); 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); 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(); mDismissIcon.animate() .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION) .setInterpolator(interpolator); mDismissCircle.animate() .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION / 2) .setInterpolator(interpolator); mDismissTargetAlphaSpring = new SpringAnimation(mDismissTarget, DynamicAnimation.ALPHA) .setSpring(new SpringForce() .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mDismissTargetVerticalSpring = new SpringAnimation(mDismissTarget, DynamicAnimation.TRANSLATION_Y) .setSpring(new SpringForce() .setStiffness(SpringForce.STIFFNESS_MEDIUM) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mDismissTargetAlphaSpring.addEndListener((anim, canceled, alpha, velocity) -> { // Since DynamicAnimations end when they're 'nearly' done, we can't rely on alpha being // exactly zero when this listener is triggered. However, if it's less than 50% we can // safely assume it was animating out rather than in. if (alpha < 0.5f) { // If the alpha spring was animating the view out, set it to GONE when it's done. setVisibility(INVISIBLE); } }); } /** Springs in the dismiss target. */ void springIn() { setVisibility(View.VISIBLE); // 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. mDismissTarget.setTranslationY(mDismissTarget.getHeight() / 2f); mDismissTargetVerticalSpring.animateToFinalPosition(0); mDismissCircle.setAlpha(0f); mDismissCircle.setScaleX(SCALE_FOR_POP); mDismissCircle.setScaleY(SCALE_FOR_POP); // Fade in circle and reduce size. mDismissCircle.animate() .alpha(1f) .scaleX(1f) .scaleY(1f); } /** 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); // Pop out the circle. mDismissCircle.animate() .scaleX(SCALE_FOR_DISMISS) .scaleY(SCALE_FOR_DISMISS) .alpha(0f); } /** Returns the Y value of the center of the dismiss target. */ float getDismissTargetCenterY() { return getTop() + mDismissTarget.getTop() + mDismissTarget.getHeight() / 2f; } /** Returns the dismiss target, which contains the text/icon and any added padding. */ View getDismissTarget() { return mDismissTarget; } } packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +15 −98 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.TransitionDrawable; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; Loading Loading @@ -95,7 +94,6 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.util.DismissCircleView; import com.android.systemui.util.FloatingContentCoordinator; import com.android.systemui.util.RelativeTouchListener; import com.android.systemui.util.animation.PhysicsAnimator; Loading Loading @@ -139,9 +137,6 @@ public class BubbleStackView extends FrameLayout /** Percent to darken the bubbles when they're in the dismiss target. */ private static final float DARKEN_PERCENT = 0.3f; /** Duration of the dismiss scrim fading in/out. */ private static final int DISMISS_TRANSITION_DURATION_MS = 200; /** How long to wait, in milliseconds, before hiding the flyout. */ @VisibleForTesting static final int FLYOUT_HIDE_AFTER = 5000; Loading Loading @@ -300,7 +295,7 @@ public class BubbleStackView extends FrameLayout public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Stack view state:"); pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress); pw.print(" showingDismiss: "); pw.println(mShowingDismiss); pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing()); pw.print(" isExpansionAnimating: "); pw.println(mIsExpansionAnimating); pw.print(" expandedContainerVis: "); pw.println(mExpandedViewContainer.getVisibility()); pw.print(" expandedContainerAlpha: "); pw.println(mExpandedViewContainer.getAlpha()); Loading Loading @@ -347,7 +342,6 @@ public class BubbleStackView extends FrameLayout private boolean mViewUpdatedRequested = false; private boolean mIsExpansionAnimating = false; private boolean mIsBubbleSwitchAnimating = false; private boolean mShowingDismiss = false; /** The view to desaturate/darken when magneted to the dismiss target. */ @Nullable private View mDesaturateAndDarkenTargetView; Loading Loading @@ -465,7 +459,7 @@ public class BubbleStackView extends FrameLayout if (wasFlungOut) { mExpandedAnimationController.snapBubbleBack( mExpandedAnimationController.getDraggedOutBubble(), velX, velY); hideDismissTarget(); mDismissView.hide(); } else { mExpandedAnimationController.onUnstuckFromTarget(); } Loading @@ -479,9 +473,9 @@ public class BubbleStackView extends FrameLayout mExpandedAnimationController.dismissDraggedOutBubble( mExpandedAnimationController.getDraggedOutBubble() /* bubble */, mDismissTargetContainer.getHeight() /* translationYBy */, mDismissView.getHeight() /* translationYBy */, BubbleStackView.this::dismissMagnetizedObject /* after */); hideDismissTarget(); mDismissView.hide(); } }; Loading @@ -502,7 +496,7 @@ public class BubbleStackView extends FrameLayout if (wasFlungOut) { mStackAnimationController.flingStackThenSpringToEdge( mStackAnimationController.getStackPosition().x, velX, velY); hideDismissTarget(); mDismissView.hide(); } else { mStackAnimationController.onUnstuckFromTarget(); } Loading @@ -511,14 +505,14 @@ public class BubbleStackView extends FrameLayout @Override public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) { mStackAnimationController.animateStackDismissal( mDismissTargetContainer.getHeight() /* translationYBy */, mDismissView.getHeight() /* translationYBy */, () -> { resetDesaturationAndDarken(); dismissMagnetizedObject(); } ); hideDismissTarget(); mDismissView.hide(); } }; Loading Loading @@ -639,7 +633,7 @@ public class BubbleStackView extends FrameLayout } // Show the dismiss target, if we haven't already. springInDismissTargetMaybe(); mDismissView.show(); // First, see if the magnetized object consumes the event - if so, we shouldn't move the // bubble since it's stuck to the target. Loading Loading @@ -681,7 +675,7 @@ public class BubbleStackView extends FrameLayout SysUiStatsLog.BUBBLE_UICHANGED__ACTION__STACK_MOVED); } hideDismissTarget(); mDismissView.hide(); } mIsDraggingStack = false; Loading Loading @@ -743,12 +737,7 @@ public class BubbleStackView extends FrameLayout } }; private View mDismissTargetCircle; private ViewGroup mDismissTargetContainer; private PhysicsAnimator<View> mDismissTargetAnimator; private PhysicsAnimator.SpringConfig mDismissTargetSpring = new PhysicsAnimator.SpringConfig( SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY); private DismissView mDismissView; private int mOrientation = Configuration.ORIENTATION_UNDEFINED; @Nullable Loading Loading @@ -866,34 +855,8 @@ public class BubbleStackView extends FrameLayout .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mFlyoutTransitionSpring.addEndListener(mAfterFlyoutTransitionSpring); final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size); mDismissTargetCircle = new DismissCircleView(context); final FrameLayout.LayoutParams newParams = new FrameLayout.LayoutParams(targetSize, targetSize); newParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; mDismissTargetCircle.setLayoutParams(newParams); mDismissTargetAnimator = PhysicsAnimator.getInstance(mDismissTargetCircle); mDismissTargetContainer = new FrameLayout(context); mDismissTargetContainer.setLayoutParams(new FrameLayout.LayoutParams( MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height), Gravity.BOTTOM)); final int bottomMargin = getResources().getDimensionPixelSize(R.dimen.floating_dismiss_bottom_margin); mDismissTargetContainer.setPadding(0, 0, 0, bottomMargin); mDismissTargetContainer.setClipToPadding(false); mDismissTargetContainer.setClipChildren(false); mDismissTargetContainer.addView(mDismissTargetCircle); mDismissTargetContainer.setVisibility(View.INVISIBLE); mDismissTargetContainer.setBackgroundResource( R.drawable.floating_dismiss_gradient_transition); addView(mDismissTargetContainer); // Start translated down so the target springs up. mDismissTargetCircle.setTranslationY( getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height)); mDismissView = new DismissView(context); addView(mDismissView); final ContentResolver contentResolver = getContext().getContentResolver(); final int dismissRadius = Settings.Secure.getInt( Loading @@ -901,7 +864,8 @@ public class BubbleStackView extends FrameLayout // Save the MagneticTarget instance for the newly set up view - we'll add this to the // MagnetizedObjects. mMagneticTarget = new MagnetizedObject.MagneticTarget(mDismissTargetCircle, dismissRadius); mMagneticTarget = new MagnetizedObject.MagneticTarget( mDismissView.getCircle(), dismissRadius); setClipChildren(false); setFocusable(true); Loading Loading @@ -1277,12 +1241,7 @@ public class BubbleStackView extends FrameLayout } mExpandedAnimationController.updateResources(mOrientation, mDisplaySize); mStackAnimationController.updateResources(mOrientation); final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size); mDismissTargetCircle.getLayoutParams().width = targetSize; mDismissTargetCircle.getLayoutParams().height = targetSize; mDismissTargetCircle.requestLayout(); mDismissView.updateResources(); mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2); } Loading Loading @@ -2360,48 +2319,6 @@ public class BubbleStackView extends FrameLayout } } /** Animates in the dismiss target. */ private void springInDismissTargetMaybe() { if (mShowingDismiss) { return; } mShowingDismiss = true; mDismissTargetContainer.bringToFront(); mDismissTargetContainer.setZ(Short.MAX_VALUE - 1); mDismissTargetContainer.setVisibility(VISIBLE); ((TransitionDrawable) mDismissTargetContainer.getBackground()).startTransition( DISMISS_TRANSITION_DURATION_MS); mDismissTargetAnimator.cancel(); mDismissTargetAnimator .spring(DynamicAnimation.TRANSLATION_Y, 0f, mDismissTargetSpring) .start(); } /** * 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 hideDismissTarget() { if (!mShowingDismiss) { return; } mShowingDismiss = false; ((TransitionDrawable) mDismissTargetContainer.getBackground()).reverseTransition( DISMISS_TRANSITION_DURATION_MS); mDismissTargetAnimator .spring(DynamicAnimation.TRANSLATION_Y, mDismissTargetContainer.getHeight(), mDismissTargetSpring) .withEndActions(() -> mDismissTargetContainer.setVisibility(View.INVISIBLE)) .start(); } /** Animates the flyout collapsed (to dot), or the reverse, starting with the given velocity. */ private void animateFlyoutCollapsed(boolean collapsed, float velX) { final boolean onLeft = mStackAnimationController.isStackOnLeftSide(); Loading packages/SystemUI/src/com/android/systemui/bubbles/DismissView.kt 0 → 100644 +85 −0 Original line number Diff line number Diff line package com.android.systemui.bubbles import android.content.Context import android.graphics.drawable.TransitionDrawable import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY import androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW import com.android.systemui.R import com.android.systemui.util.DismissCircleView import com.android.systemui.util.animation.PhysicsAnimator /* * View that handles interactions between DismissCircleView and BubbleStackView. */ class DismissView(context: Context) : FrameLayout(context) { var circle = DismissCircleView(context).apply { val targetSize: Int = context.resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) val newParams = LayoutParams(targetSize, targetSize) newParams.gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL setLayoutParams(newParams) setTranslationY( resources.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height).toFloat()) } var isShowing = false private val animator = PhysicsAnimator.getInstance(circle) private val spring = PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY); private val DISMISS_SCRIM_FADE_MS = 200 init { setLayoutParams(LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, resources.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height), Gravity.BOTTOM)) setPadding(0, 0, 0, resources.getDimensionPixelSize(R.dimen.floating_dismiss_bottom_margin)) setClipToPadding(false) setClipChildren(false) setVisibility(View.INVISIBLE) setBackgroundResource( R.drawable.floating_dismiss_gradient_transition) addView(circle) } /** * Animates this view in. */ fun show() { if (isShowing) return isShowing = true bringToFront() setZ(Short.MAX_VALUE - 1f) setVisibility(View.VISIBLE) (getBackground() as TransitionDrawable).startTransition(DISMISS_SCRIM_FADE_MS) animator.cancel() animator .spring(DynamicAnimation.TRANSLATION_Y, 0f, spring) .start() } /** * Animates this view out, as well as the circle that encircles the bubbles, if they * were dragged into the target and encircled. */ fun hide() { if (!isShowing) return isShowing = false (getBackground() as TransitionDrawable).reverseTransition(DISMISS_SCRIM_FADE_MS) animator .spring(DynamicAnimation.TRANSLATION_Y, height.toFloat(), spring) .withEndActions({ setVisibility(View.INVISIBLE) }) .start() } fun updateResources() { val targetSize: Int = context.resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) circle.layoutParams.width = targetSize circle.layoutParams.height = targetSize circle.requestLayout() } } No newline at end of file Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleDismissView.javadeleted 100644 → 0 +0 −148 Original line number Diff line number Diff line /* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.bubbles; import android.content.Context; 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 androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; 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. */ private static final int DISMISS_TARGET_ANIMATION_BASE_DURATION = 150; 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 View mDismissCircle; private SpringAnimation mDismissTargetAlphaSpring; private SpringAnimation mDismissTargetVerticalSpring; public BubbleDismissView(Context context) { super(context); setVisibility(GONE); 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); 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(); mDismissIcon.animate() .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION) .setInterpolator(interpolator); mDismissCircle.animate() .setDuration(DISMISS_TARGET_ANIMATION_BASE_DURATION / 2) .setInterpolator(interpolator); mDismissTargetAlphaSpring = new SpringAnimation(mDismissTarget, DynamicAnimation.ALPHA) .setSpring(new SpringForce() .setStiffness(SpringForce.STIFFNESS_LOW) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mDismissTargetVerticalSpring = new SpringAnimation(mDismissTarget, DynamicAnimation.TRANSLATION_Y) .setSpring(new SpringForce() .setStiffness(SpringForce.STIFFNESS_MEDIUM) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mDismissTargetAlphaSpring.addEndListener((anim, canceled, alpha, velocity) -> { // Since DynamicAnimations end when they're 'nearly' done, we can't rely on alpha being // exactly zero when this listener is triggered. However, if it's less than 50% we can // safely assume it was animating out rather than in. if (alpha < 0.5f) { // If the alpha spring was animating the view out, set it to GONE when it's done. setVisibility(INVISIBLE); } }); } /** Springs in the dismiss target. */ void springIn() { setVisibility(View.VISIBLE); // 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. mDismissTarget.setTranslationY(mDismissTarget.getHeight() / 2f); mDismissTargetVerticalSpring.animateToFinalPosition(0); mDismissCircle.setAlpha(0f); mDismissCircle.setScaleX(SCALE_FOR_POP); mDismissCircle.setScaleY(SCALE_FOR_POP); // Fade in circle and reduce size. mDismissCircle.animate() .alpha(1f) .scaleX(1f) .scaleY(1f); } /** 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); // Pop out the circle. mDismissCircle.animate() .scaleX(SCALE_FOR_DISMISS) .scaleY(SCALE_FOR_DISMISS) .alpha(0f); } /** Returns the Y value of the center of the dismiss target. */ float getDismissTargetCenterY() { return getTop() + mDismissTarget.getTop() + mDismissTarget.getHeight() / 2f; } /** Returns the dismiss target, which contains the text/icon and any added padding. */ View getDismissTarget() { return mDismissTarget; } }
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +15 −98 Original line number Diff line number Diff line Loading @@ -48,7 +48,6 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.drawable.TransitionDrawable; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; Loading Loading @@ -95,7 +94,6 @@ import com.android.systemui.model.SysUiState; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; import com.android.systemui.util.DismissCircleView; import com.android.systemui.util.FloatingContentCoordinator; import com.android.systemui.util.RelativeTouchListener; import com.android.systemui.util.animation.PhysicsAnimator; Loading Loading @@ -139,9 +137,6 @@ public class BubbleStackView extends FrameLayout /** Percent to darken the bubbles when they're in the dismiss target. */ private static final float DARKEN_PERCENT = 0.3f; /** Duration of the dismiss scrim fading in/out. */ private static final int DISMISS_TRANSITION_DURATION_MS = 200; /** How long to wait, in milliseconds, before hiding the flyout. */ @VisibleForTesting static final int FLYOUT_HIDE_AFTER = 5000; Loading Loading @@ -300,7 +295,7 @@ public class BubbleStackView extends FrameLayout public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Stack view state:"); pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress); pw.print(" showingDismiss: "); pw.println(mShowingDismiss); pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing()); pw.print(" isExpansionAnimating: "); pw.println(mIsExpansionAnimating); pw.print(" expandedContainerVis: "); pw.println(mExpandedViewContainer.getVisibility()); pw.print(" expandedContainerAlpha: "); pw.println(mExpandedViewContainer.getAlpha()); Loading Loading @@ -347,7 +342,6 @@ public class BubbleStackView extends FrameLayout private boolean mViewUpdatedRequested = false; private boolean mIsExpansionAnimating = false; private boolean mIsBubbleSwitchAnimating = false; private boolean mShowingDismiss = false; /** The view to desaturate/darken when magneted to the dismiss target. */ @Nullable private View mDesaturateAndDarkenTargetView; Loading Loading @@ -465,7 +459,7 @@ public class BubbleStackView extends FrameLayout if (wasFlungOut) { mExpandedAnimationController.snapBubbleBack( mExpandedAnimationController.getDraggedOutBubble(), velX, velY); hideDismissTarget(); mDismissView.hide(); } else { mExpandedAnimationController.onUnstuckFromTarget(); } Loading @@ -479,9 +473,9 @@ public class BubbleStackView extends FrameLayout mExpandedAnimationController.dismissDraggedOutBubble( mExpandedAnimationController.getDraggedOutBubble() /* bubble */, mDismissTargetContainer.getHeight() /* translationYBy */, mDismissView.getHeight() /* translationYBy */, BubbleStackView.this::dismissMagnetizedObject /* after */); hideDismissTarget(); mDismissView.hide(); } }; Loading @@ -502,7 +496,7 @@ public class BubbleStackView extends FrameLayout if (wasFlungOut) { mStackAnimationController.flingStackThenSpringToEdge( mStackAnimationController.getStackPosition().x, velX, velY); hideDismissTarget(); mDismissView.hide(); } else { mStackAnimationController.onUnstuckFromTarget(); } Loading @@ -511,14 +505,14 @@ public class BubbleStackView extends FrameLayout @Override public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) { mStackAnimationController.animateStackDismissal( mDismissTargetContainer.getHeight() /* translationYBy */, mDismissView.getHeight() /* translationYBy */, () -> { resetDesaturationAndDarken(); dismissMagnetizedObject(); } ); hideDismissTarget(); mDismissView.hide(); } }; Loading Loading @@ -639,7 +633,7 @@ public class BubbleStackView extends FrameLayout } // Show the dismiss target, if we haven't already. springInDismissTargetMaybe(); mDismissView.show(); // First, see if the magnetized object consumes the event - if so, we shouldn't move the // bubble since it's stuck to the target. Loading Loading @@ -681,7 +675,7 @@ public class BubbleStackView extends FrameLayout SysUiStatsLog.BUBBLE_UICHANGED__ACTION__STACK_MOVED); } hideDismissTarget(); mDismissView.hide(); } mIsDraggingStack = false; Loading Loading @@ -743,12 +737,7 @@ public class BubbleStackView extends FrameLayout } }; private View mDismissTargetCircle; private ViewGroup mDismissTargetContainer; private PhysicsAnimator<View> mDismissTargetAnimator; private PhysicsAnimator.SpringConfig mDismissTargetSpring = new PhysicsAnimator.SpringConfig( SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY); private DismissView mDismissView; private int mOrientation = Configuration.ORIENTATION_UNDEFINED; @Nullable Loading Loading @@ -866,34 +855,8 @@ public class BubbleStackView extends FrameLayout .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)); mFlyoutTransitionSpring.addEndListener(mAfterFlyoutTransitionSpring); final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size); mDismissTargetCircle = new DismissCircleView(context); final FrameLayout.LayoutParams newParams = new FrameLayout.LayoutParams(targetSize, targetSize); newParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; mDismissTargetCircle.setLayoutParams(newParams); mDismissTargetAnimator = PhysicsAnimator.getInstance(mDismissTargetCircle); mDismissTargetContainer = new FrameLayout(context); mDismissTargetContainer.setLayoutParams(new FrameLayout.LayoutParams( MATCH_PARENT, getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height), Gravity.BOTTOM)); final int bottomMargin = getResources().getDimensionPixelSize(R.dimen.floating_dismiss_bottom_margin); mDismissTargetContainer.setPadding(0, 0, 0, bottomMargin); mDismissTargetContainer.setClipToPadding(false); mDismissTargetContainer.setClipChildren(false); mDismissTargetContainer.addView(mDismissTargetCircle); mDismissTargetContainer.setVisibility(View.INVISIBLE); mDismissTargetContainer.setBackgroundResource( R.drawable.floating_dismiss_gradient_transition); addView(mDismissTargetContainer); // Start translated down so the target springs up. mDismissTargetCircle.setTranslationY( getResources().getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height)); mDismissView = new DismissView(context); addView(mDismissView); final ContentResolver contentResolver = getContext().getContentResolver(); final int dismissRadius = Settings.Secure.getInt( Loading @@ -901,7 +864,8 @@ public class BubbleStackView extends FrameLayout // Save the MagneticTarget instance for the newly set up view - we'll add this to the // MagnetizedObjects. mMagneticTarget = new MagnetizedObject.MagneticTarget(mDismissTargetCircle, dismissRadius); mMagneticTarget = new MagnetizedObject.MagneticTarget( mDismissView.getCircle(), dismissRadius); setClipChildren(false); setFocusable(true); Loading Loading @@ -1277,12 +1241,7 @@ public class BubbleStackView extends FrameLayout } mExpandedAnimationController.updateResources(mOrientation, mDisplaySize); mStackAnimationController.updateResources(mOrientation); final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size); mDismissTargetCircle.getLayoutParams().width = targetSize; mDismissTargetCircle.getLayoutParams().height = targetSize; mDismissTargetCircle.requestLayout(); mDismissView.updateResources(); mMagneticTarget.setMagneticFieldRadiusPx(mBubbleSize * 2); } Loading Loading @@ -2360,48 +2319,6 @@ public class BubbleStackView extends FrameLayout } } /** Animates in the dismiss target. */ private void springInDismissTargetMaybe() { if (mShowingDismiss) { return; } mShowingDismiss = true; mDismissTargetContainer.bringToFront(); mDismissTargetContainer.setZ(Short.MAX_VALUE - 1); mDismissTargetContainer.setVisibility(VISIBLE); ((TransitionDrawable) mDismissTargetContainer.getBackground()).startTransition( DISMISS_TRANSITION_DURATION_MS); mDismissTargetAnimator.cancel(); mDismissTargetAnimator .spring(DynamicAnimation.TRANSLATION_Y, 0f, mDismissTargetSpring) .start(); } /** * 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 hideDismissTarget() { if (!mShowingDismiss) { return; } mShowingDismiss = false; ((TransitionDrawable) mDismissTargetContainer.getBackground()).reverseTransition( DISMISS_TRANSITION_DURATION_MS); mDismissTargetAnimator .spring(DynamicAnimation.TRANSLATION_Y, mDismissTargetContainer.getHeight(), mDismissTargetSpring) .withEndActions(() -> mDismissTargetContainer.setVisibility(View.INVISIBLE)) .start(); } /** Animates the flyout collapsed (to dot), or the reverse, starting with the given velocity. */ private void animateFlyoutCollapsed(boolean collapsed, float velX) { final boolean onLeft = mStackAnimationController.isStackOnLeftSide(); Loading
packages/SystemUI/src/com/android/systemui/bubbles/DismissView.kt 0 → 100644 +85 −0 Original line number Diff line number Diff line package com.android.systemui.bubbles import android.content.Context import android.graphics.drawable.TransitionDrawable import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY import androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW import com.android.systemui.R import com.android.systemui.util.DismissCircleView import com.android.systemui.util.animation.PhysicsAnimator /* * View that handles interactions between DismissCircleView and BubbleStackView. */ class DismissView(context: Context) : FrameLayout(context) { var circle = DismissCircleView(context).apply { val targetSize: Int = context.resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) val newParams = LayoutParams(targetSize, targetSize) newParams.gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL setLayoutParams(newParams) setTranslationY( resources.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height).toFloat()) } var isShowing = false private val animator = PhysicsAnimator.getInstance(circle) private val spring = PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY); private val DISMISS_SCRIM_FADE_MS = 200 init { setLayoutParams(LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, resources.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height), Gravity.BOTTOM)) setPadding(0, 0, 0, resources.getDimensionPixelSize(R.dimen.floating_dismiss_bottom_margin)) setClipToPadding(false) setClipChildren(false) setVisibility(View.INVISIBLE) setBackgroundResource( R.drawable.floating_dismiss_gradient_transition) addView(circle) } /** * Animates this view in. */ fun show() { if (isShowing) return isShowing = true bringToFront() setZ(Short.MAX_VALUE - 1f) setVisibility(View.VISIBLE) (getBackground() as TransitionDrawable).startTransition(DISMISS_SCRIM_FADE_MS) animator.cancel() animator .spring(DynamicAnimation.TRANSLATION_Y, 0f, spring) .start() } /** * Animates this view out, as well as the circle that encircles the bubbles, if they * were dragged into the target and encircled. */ fun hide() { if (!isShowing) return isShowing = false (getBackground() as TransitionDrawable).reverseTransition(DISMISS_SCRIM_FADE_MS) animator .spring(DynamicAnimation.TRANSLATION_Y, height.toFloat(), spring) .withEndActions({ setVisibility(View.INVISIBLE) }) .start() } fun updateResources() { val targetSize: Int = context.resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) circle.layoutParams.width = targetSize circle.layoutParams.height = targetSize circle.requestLayout() } } No newline at end of file