Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +10 −6 Original line number Diff line number Diff line Loading @@ -419,9 +419,7 @@ public class BubbleBarController extends IBubblesListener.Stub { } if (update.bubbleBarLocation != null) { if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) { // Animate when receiving updates. Skip it if we received the initial state. boolean animate = !update.initialState; updateBubbleBarLocationInternal(update.bubbleBarLocation, animate); updateBubbleBarLocationInternal(update.bubbleBarLocation); } } } Loading Loading @@ -483,15 +481,21 @@ public class BubbleBarController extends IBubblesListener.Stub { * Updates the value locally in Launcher and in WMShell. */ public void updateBubbleBarLocation(BubbleBarLocation location) { updateBubbleBarLocationInternal(location, false /* animate */); updateBubbleBarLocationInternal(location); mSystemUiProxy.setBubbleBarLocation(location); } private void updateBubbleBarLocationInternal(BubbleBarLocation location, boolean animate) { mBubbleBarViewController.setBubbleBarLocation(location, animate); private void updateBubbleBarLocationInternal(BubbleBarLocation location) { mBubbleBarViewController.setBubbleBarLocation(location); mBubbleStashController.setBubbleBarLocation(location); } @Override public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mMainExecutor.execute( () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation)); } // // Loading data for the bubbles // Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +78 −79 Original line number Diff line number Diff line Loading @@ -153,8 +153,6 @@ public class BubbleBarView extends FrameLayout { private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED; private boolean mLocationChangePending; public BubbleBarView(Context context) { this(context, null); } Loading Loading @@ -188,7 +186,7 @@ public class BubbleBarView extends FrameLayout { mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS); mWidthAnimator.addUpdateListener(animation -> { updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); invalidate(); }); mWidthAnimator.addListener(new Animator.AnimatorListener() { Loading Loading @@ -262,7 +260,7 @@ public class BubbleBarView extends FrameLayout { setPivotY(mRelativePivotY * getHeight()); // Position the views updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); } @Override Loading @@ -278,7 +276,6 @@ public class BubbleBarView extends FrameLayout { @SuppressLint("RtlHardcoded") private void onBubbleBarLocationChanged() { mLocationChangePending = false; final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); mBubbleBarBackground.setAnchorLeft(onLeft); mRelativePivotX = onLeft ? 0f : 1f; Loading @@ -299,11 +296,18 @@ public class BubbleBarView extends FrameLayout { /** * Update {@link BubbleBarLocation} */ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) { if (animate) { animateToBubbleBarLocation(bubbleBarLocation); } else { setBubbleBarLocationInternal(bubbleBarLocation); public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (mBubbleBarLocationAnimator != null) { mBubbleBarLocationAnimator.removeAllListeners(); mBubbleBarLocationAnimator.cancel(); mBubbleBarLocationAnimator = null; } setTranslationX(0f); setAlpha(1f); if (bubbleBarLocation != mBubbleBarLocation) { mBubbleBarLocation = bubbleBarLocation; onBubbleBarLocationChanged(); invalidate(); } } Loading @@ -316,51 +320,37 @@ public class BubbleBarView extends FrameLayout { } mDragging = dragging; setElevation(dragging ? mDragElevation : mBubbleElevation); if (!dragging && mLocationChangePending) { // During drag finish animation we may update the translation x value to shift the // bubble to the new drop target. Clear the translation here. setTranslationX(0f); onBubbleBarLocationChanged(); } } /** * Adjust resting position for the bubble bar while it is being dragged. * <p> * Bubble bar is laid out on left or right side of the screen. When it is being dragged to * the opposite side, the resting position should be on that side. Calculate any additional * translation that may be required to move the bubble bar to the new side. * Get translation for bubble bar when drag is released and it needs to animate back to the * resting position. * Resting position is based on the supplied location. If the supplied location is different * from the internal location that was used to lay out the bubble bar, translation values are * calculated to position the bar at the desired location. * * @param restingPosition relative resting position of the bubble bar from the laid out position * @param initialTranslation initial bubble bar translation at the start of drag * @param location desired location of the bubble bar when drag is released * @return point with x and y values representing translation on x and y-axis */ @SuppressLint("RtlHardcoded") void adjustRelativeRestingPosition(PointF restingPosition) { final boolean locationOnLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); // Bubble bar is placed left or right with gravity. Check where it is currently. final int absoluteGravity = Gravity.getAbsoluteGravity( ((LayoutParams) getLayoutParams()).gravity, getLayoutDirection()); final boolean gravityOnLeft = (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT; // Bubble bar is pinned to the same side per gravity and the desired location. // Resting translation does not need to be adjusted. if (locationOnLeft == gravityOnLeft) { return; } public PointF getBubbleBarDragReleaseTranslation(PointF initialTranslation, BubbleBarLocation location) { // Start with the initial translation. Value on y-axis can be reused. final PointF dragEndTranslation = new PointF(initialTranslation); // Bubble bar is laid out on left or right side of the screen. And the desired new // location is on the other side. Calculate x translation value required to shift the // location is on the other side. Calculate x translation value required to shift // bubble bar from one side to the other. float x = getDistanceFromOtherSide(); if (locationOnLeft) { final float shift = getDistanceFromOtherSide(); if (location.isOnLeft(isLayoutRtl())) { // New location is on the left, shift left // before -> |......ooo.| after -> |.ooo......| restingPosition.x = -x; dragEndTranslation.x = -shift; } else { // New location is on the right, shift right // before -> |.ooo......| after -> |......ooo.| restingPosition.x = x; dragEndTranslation.x = shift; } return dragEndTranslation; } private float getDistanceFromOtherSide() { Loading @@ -374,49 +364,40 @@ public class BubbleBarView extends FrameLayout { return (float) (displayWidth - getWidth() - margin); } private void setBubbleBarLocationInternal(BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation != mBubbleBarLocation) { mBubbleBarLocation = bubbleBarLocation; if (mDragging) { mLocationChangePending = true; } else { onBubbleBarLocationChanged(); invalidate(); } } } private void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == mBubbleBarLocation) { // nothing to do, already at expected location return; } /** * Animate bubble bar to the given location transiently. Does not modify the layout or the value * returned by {@link #getBubbleBarLocation()}. */ public void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (mBubbleBarLocationAnimator != null && mBubbleBarLocationAnimator.isRunning()) { mBubbleBarLocationAnimator.removeAllListeners(); mBubbleBarLocationAnimator.cancel(); } // Location animation uses two separate animators. // First animator hides the bar. // After it completes, location update is sent to layout the bar in the new location. // After it completes, bubble positions in the bar and arrow position is updated. // Second animator is started to show the bar. mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(); mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(bubbleBarLocation); mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // Bubble bar is not visible, update the location setBubbleBarLocationInternal(bubbleBarLocation); updateChildrenRenderNodeProperties(bubbleBarLocation); mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl())); // Animate it in mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(); mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(bubbleBarLocation); mBubbleBarLocationAnimator.start(); } }); mBubbleBarLocationAnimator.start(); } private AnimatorSet getLocationUpdateFadeOutAnimator() { private Animator getLocationUpdateFadeOutAnimator(BubbleBarLocation bubbleBarLocation) { final float shift = getResources().getDisplayMetrics().widthPixels * FADE_OUT_ANIM_POSITION_SHIFT; final float tx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift; final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); final float tx = getTranslationX() + (onLeft ? shift : -shift); ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, TRANSLATION_X, tx) .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS); Loading @@ -431,14 +412,31 @@ public class BubbleBarView extends FrameLayout { return animatorSet; } private Animator getLocationUpdateFadeInAnimator() { private Animator getLocationUpdateFadeInAnimator(BubbleBarLocation animatedLocation) { final float shift = getResources().getDisplayMetrics().widthPixels * FADE_IN_ANIM_POSITION_SHIFT; final float startTx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift; final boolean onLeft = animatedLocation.isOnLeft(isLayoutRtl()); final float startTx; final float finalTx; if (animatedLocation == mBubbleBarLocation) { // Animated location matches layout location. finalTx = 0; } else { // We are animating in to a transient location, need to move the bar accordingly. finalTx = getDistanceFromOtherSide() * (onLeft ? -1 : 1); } if (onLeft) { // Bar will be shown on the left side. Start point is shifted right. startTx = finalTx + shift; } else { // Bar will be shown on the right side. Start point is shifted left. startTx = finalTx - shift; } ValueAnimator positionAnim = new SpringAnimationBuilder(getContext()) .setStartValue(startTx) .setEndValue(0) .setEndValue(finalTx) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS) .build(this, VIEW_TRANSLATE_X); Loading Loading @@ -547,7 +545,7 @@ public class BubbleBarView extends FrameLayout { * Updates the z order, positions, and badge visibility of the bubble views in the bar based * on the expanded state. */ private void updateChildrenRenderNodeProperties() { private void updateChildrenRenderNodeProperties(BubbleBarLocation bubbleBarLocation) { final float widthState = (float) mWidthAnimator.getAnimatedValue(); final float currentWidth = getWidth(); final float expandedWidth = expandedWidth(); Loading @@ -555,7 +553,7 @@ public class BubbleBarView extends FrameLayout { int bubbleCount = getChildCount(); final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f; final boolean animate = getVisibility() == VISIBLE; final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); // elevation state is opposite to widthState - when expanded all icons are flat float elevationState = (1 - widthState); for (int i = 0; i < bubbleCount; i++) { Loading Loading @@ -613,8 +611,9 @@ public class BubbleBarView extends FrameLayout { } // update the arrow position final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed(); final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded(); final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed( bubbleBarLocation); final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded(bubbleBarLocation); final float interpolatedWidth = widthState * (expandedWidth - collapsedWidth) + collapsedWidth; final float arrowPosition; Loading Loading @@ -661,7 +660,7 @@ public class BubbleBarView extends FrameLayout { addViewInLayout(child, i, child.getLayoutParams()); } } updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); } } Loading Loading @@ -702,7 +701,7 @@ public class BubbleBarView extends FrameLayout { return; } // Find the center of the bubble when it's expanded, set the arrow position to it. final float tx = arrowPositionForSelectedWhenExpanded(); final float tx = arrowPositionForSelectedWhenExpanded(mBubbleBarLocation); final float currentArrowPosition = mBubbleBarBackground.getArrowPositionX(); if (tx == currentArrowPosition) { // arrow position remains unchanged Loading @@ -727,10 +726,10 @@ public class BubbleBarView extends FrameLayout { } } private float arrowPositionForSelectedWhenExpanded() { private float arrowPositionForSelectedWhenExpanded(BubbleBarLocation bubbleBarLocation) { final int index = indexOfChild(mSelectedBubbleView); final int bubblePosition; if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) { if (bubbleBarLocation.isOnLeft(isLayoutRtl())) { // Bubble positions are reversed. First bubble is on the right. bubblePosition = getChildCount() - index - 1; } else { Loading @@ -740,10 +739,10 @@ public class BubbleBarView extends FrameLayout { + mIconSize / 2f; } private float arrowPositionForSelectedWhenCollapsed() { private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) { final int index = indexOfChild(mSelectedBubbleView); final int bubblePosition; if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) { if (bubbleBarLocation.isOnLeft(isLayoutRtl())) { // Bubble positions are reversed. First bubble may be shifted, if there are more // bubbles than the current bubble and overflow. bubblePosition = index == 0 && getChildCount() > 2 ? 1 : 0; Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +11 −2 Original line number Diff line number Diff line Loading @@ -215,8 +215,17 @@ public class BubbleBarViewController { /** * Update bar {@link BubbleBarLocation} */ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) { mBarView.setBubbleBarLocation(bubbleBarLocation, animate); public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mBarView.setBubbleBarLocation(bubbleBarLocation); } /** * Animate bubble bar to the given location. The location change is transient. It does not * update the state of the bubble bar. * To update bubble bar pinned location, use {@link #setBubbleBarLocation(BubbleBarLocation)}. */ public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mBarView.animateToBubbleBarLocation(bubbleBarLocation); } /** Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java +5 −5 Original line number Diff line number Diff line Loading @@ -110,25 +110,25 @@ public class BubbleDragAnimator { /** * Animates the dragged bubble movement back to the initial position. * * @param initialPosition the position to animate to * @param restingPosition the position to animate to * @param velocity the initial velocity to use for the spring animation * @param endActions gets called when the animation completes or gets cancelled */ public void animateToInitialState(@NonNull PointF initialPosition, @NonNull PointF velocity, public void animateToRestingState(@NonNull PointF restingPosition, @NonNull PointF velocity, @Nullable Runnable endActions) { mBubbleAnimator.cancel(); mBubbleAnimator .spring(DynamicAnimation.SCALE_X, 1f) .spring(DynamicAnimation.SCALE_Y, 1f) .spring(DynamicAnimation.TRANSLATION_X, initialPosition.x, velocity.x, .spring(DynamicAnimation.TRANSLATION_X, restingPosition.x, velocity.x, mTranslationConfig) .spring(DynamicAnimation.TRANSLATION_Y, initialPosition.y, velocity.y, .spring(DynamicAnimation.TRANSLATION_Y, restingPosition.y, velocity.y, mTranslationConfig) .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property, boolean wasFling, boolean canceled, float finalValue, float finalVelocity, boolean allRelevantPropertyAnimationsEnded) -> { if (canceled || allRelevantPropertyAnimationsEnded) { resetAnimatedViews(initialPosition); resetAnimatedViews(restingPosition); if (endActions != null) { endActions.run(); } Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java +31 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.wm.shell.common.bubbles.BaseBubblePinController.LocationChangeListener; import com.android.wm.shell.common.bubbles.BubbleBarLocation; /** * Controls bubble bar drag interactions. Loading @@ -37,6 +39,7 @@ import com.android.launcher3.taskbar.TaskbarActivityContext; */ public class BubbleDragController { private final TaskbarActivityContext mActivity; private BubbleBarController mBubbleBarController; private BubbleBarViewController mBubbleBarViewController; private BubbleDismissController mBubbleDismissController; private BubbleBarPinController mBubbleBarPinController; Loading @@ -51,11 +54,10 @@ public class BubbleDragController { * controllers may still be waiting for init(). */ public void init(@NonNull BubbleControllers bubbleControllers) { mBubbleBarController = bubbleControllers.bubbleBarController; mBubbleBarViewController = bubbleControllers.bubbleBarViewController; mBubbleDismissController = bubbleControllers.bubbleDismissController; mBubbleBarPinController = bubbleControllers.bubbleBarPinController; mBubbleBarPinController.setListener( bubbleControllers.bubbleBarController::updateBubbleBarLocation); mBubbleDismissController.setListener( stuck -> mBubbleBarPinController.setDropTargetHidden(stuck)); } Loading Loading @@ -96,6 +98,17 @@ public class BubbleDragController { PointF initialRelativePivot = new PointF(); bubbleBarView.setOnTouchListener(new BubbleTouchListener() { @Nullable private BubbleBarLocation mReleasedLocation; private final LocationChangeListener mLocationChangeListener = new LocationChangeListener() { @Override public void onRelease(@NonNull BubbleBarLocation location) { mReleasedLocation = location; } }; @Override protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) { if (bubbleBarView.isExpanded()) return false; Loading @@ -104,6 +117,7 @@ public class BubbleDragController { @Override void onDragStart() { mBubbleBarPinController.setListener(mLocationChangeListener); initialRelativePivot.set(bubbleBarView.getRelativePivotX(), bubbleBarView.getRelativePivotY()); // By default the bubble bar view pivot is in bottom right corner, while dragging Loading Loading @@ -134,13 +148,17 @@ public class BubbleDragController { // Restoring the initial pivot for the bubble bar view bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y); bubbleBarView.setIsDragging(false); mBubbleBarController.updateBubbleBarLocation(mReleasedLocation); } @Override protected PointF getRestingPosition() { PointF restingPosition = super.getRestingPosition(); bubbleBarView.adjustRelativeRestingPosition(restingPosition); return restingPosition; if (mReleasedLocation == null || mReleasedLocation == bubbleBarView.getBubbleBarLocation()) { return getInitialPosition(); } return bubbleBarView.getBubbleBarDragReleaseTranslation(getInitialPosition(), mReleasedLocation); } }); } Loading Loading @@ -228,6 +246,13 @@ public class BubbleDragController { protected void onDragDismiss() { } /** * Get the initial position of the view when drag started */ protected PointF getInitialPosition() { return mViewInitialPosition; } /** * Get the resting position of the view when drag is released */ Loading Loading @@ -362,7 +387,7 @@ public class BubbleDragController { mAnimator.animateDismiss(mViewInitialPosition, onComplete); } else { onDragRelease(); mAnimator.animateToInitialState(getRestingPosition(), getCurrentVelocity(), mAnimator.animateToRestingState(getRestingPosition(), getCurrentVelocity(), onComplete); } mBubbleDismissController.hideDismissView(); Loading Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +10 −6 Original line number Diff line number Diff line Loading @@ -419,9 +419,7 @@ public class BubbleBarController extends IBubblesListener.Stub { } if (update.bubbleBarLocation != null) { if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) { // Animate when receiving updates. Skip it if we received the initial state. boolean animate = !update.initialState; updateBubbleBarLocationInternal(update.bubbleBarLocation, animate); updateBubbleBarLocationInternal(update.bubbleBarLocation); } } } Loading Loading @@ -483,15 +481,21 @@ public class BubbleBarController extends IBubblesListener.Stub { * Updates the value locally in Launcher and in WMShell. */ public void updateBubbleBarLocation(BubbleBarLocation location) { updateBubbleBarLocationInternal(location, false /* animate */); updateBubbleBarLocationInternal(location); mSystemUiProxy.setBubbleBarLocation(location); } private void updateBubbleBarLocationInternal(BubbleBarLocation location, boolean animate) { mBubbleBarViewController.setBubbleBarLocation(location, animate); private void updateBubbleBarLocationInternal(BubbleBarLocation location) { mBubbleBarViewController.setBubbleBarLocation(location); mBubbleStashController.setBubbleBarLocation(location); } @Override public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mMainExecutor.execute( () -> mBubbleBarViewController.animateBubbleBarLocation(bubbleBarLocation)); } // // Loading data for the bubbles // Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +78 −79 Original line number Diff line number Diff line Loading @@ -153,8 +153,6 @@ public class BubbleBarView extends FrameLayout { private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED; private boolean mLocationChangePending; public BubbleBarView(Context context) { this(context, null); } Loading Loading @@ -188,7 +186,7 @@ public class BubbleBarView extends FrameLayout { mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS); mWidthAnimator.addUpdateListener(animation -> { updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); invalidate(); }); mWidthAnimator.addListener(new Animator.AnimatorListener() { Loading Loading @@ -262,7 +260,7 @@ public class BubbleBarView extends FrameLayout { setPivotY(mRelativePivotY * getHeight()); // Position the views updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); } @Override Loading @@ -278,7 +276,6 @@ public class BubbleBarView extends FrameLayout { @SuppressLint("RtlHardcoded") private void onBubbleBarLocationChanged() { mLocationChangePending = false; final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); mBubbleBarBackground.setAnchorLeft(onLeft); mRelativePivotX = onLeft ? 0f : 1f; Loading @@ -299,11 +296,18 @@ public class BubbleBarView extends FrameLayout { /** * Update {@link BubbleBarLocation} */ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) { if (animate) { animateToBubbleBarLocation(bubbleBarLocation); } else { setBubbleBarLocationInternal(bubbleBarLocation); public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (mBubbleBarLocationAnimator != null) { mBubbleBarLocationAnimator.removeAllListeners(); mBubbleBarLocationAnimator.cancel(); mBubbleBarLocationAnimator = null; } setTranslationX(0f); setAlpha(1f); if (bubbleBarLocation != mBubbleBarLocation) { mBubbleBarLocation = bubbleBarLocation; onBubbleBarLocationChanged(); invalidate(); } } Loading @@ -316,51 +320,37 @@ public class BubbleBarView extends FrameLayout { } mDragging = dragging; setElevation(dragging ? mDragElevation : mBubbleElevation); if (!dragging && mLocationChangePending) { // During drag finish animation we may update the translation x value to shift the // bubble to the new drop target. Clear the translation here. setTranslationX(0f); onBubbleBarLocationChanged(); } } /** * Adjust resting position for the bubble bar while it is being dragged. * <p> * Bubble bar is laid out on left or right side of the screen. When it is being dragged to * the opposite side, the resting position should be on that side. Calculate any additional * translation that may be required to move the bubble bar to the new side. * Get translation for bubble bar when drag is released and it needs to animate back to the * resting position. * Resting position is based on the supplied location. If the supplied location is different * from the internal location that was used to lay out the bubble bar, translation values are * calculated to position the bar at the desired location. * * @param restingPosition relative resting position of the bubble bar from the laid out position * @param initialTranslation initial bubble bar translation at the start of drag * @param location desired location of the bubble bar when drag is released * @return point with x and y values representing translation on x and y-axis */ @SuppressLint("RtlHardcoded") void adjustRelativeRestingPosition(PointF restingPosition) { final boolean locationOnLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); // Bubble bar is placed left or right with gravity. Check where it is currently. final int absoluteGravity = Gravity.getAbsoluteGravity( ((LayoutParams) getLayoutParams()).gravity, getLayoutDirection()); final boolean gravityOnLeft = (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT; // Bubble bar is pinned to the same side per gravity and the desired location. // Resting translation does not need to be adjusted. if (locationOnLeft == gravityOnLeft) { return; } public PointF getBubbleBarDragReleaseTranslation(PointF initialTranslation, BubbleBarLocation location) { // Start with the initial translation. Value on y-axis can be reused. final PointF dragEndTranslation = new PointF(initialTranslation); // Bubble bar is laid out on left or right side of the screen. And the desired new // location is on the other side. Calculate x translation value required to shift the // location is on the other side. Calculate x translation value required to shift // bubble bar from one side to the other. float x = getDistanceFromOtherSide(); if (locationOnLeft) { final float shift = getDistanceFromOtherSide(); if (location.isOnLeft(isLayoutRtl())) { // New location is on the left, shift left // before -> |......ooo.| after -> |.ooo......| restingPosition.x = -x; dragEndTranslation.x = -shift; } else { // New location is on the right, shift right // before -> |.ooo......| after -> |......ooo.| restingPosition.x = x; dragEndTranslation.x = shift; } return dragEndTranslation; } private float getDistanceFromOtherSide() { Loading @@ -374,49 +364,40 @@ public class BubbleBarView extends FrameLayout { return (float) (displayWidth - getWidth() - margin); } private void setBubbleBarLocationInternal(BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation != mBubbleBarLocation) { mBubbleBarLocation = bubbleBarLocation; if (mDragging) { mLocationChangePending = true; } else { onBubbleBarLocationChanged(); invalidate(); } } } private void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (bubbleBarLocation == mBubbleBarLocation) { // nothing to do, already at expected location return; } /** * Animate bubble bar to the given location transiently. Does not modify the layout or the value * returned by {@link #getBubbleBarLocation()}. */ public void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { if (mBubbleBarLocationAnimator != null && mBubbleBarLocationAnimator.isRunning()) { mBubbleBarLocationAnimator.removeAllListeners(); mBubbleBarLocationAnimator.cancel(); } // Location animation uses two separate animators. // First animator hides the bar. // After it completes, location update is sent to layout the bar in the new location. // After it completes, bubble positions in the bar and arrow position is updated. // Second animator is started to show the bar. mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(); mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator(bubbleBarLocation); mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // Bubble bar is not visible, update the location setBubbleBarLocationInternal(bubbleBarLocation); updateChildrenRenderNodeProperties(bubbleBarLocation); mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl())); // Animate it in mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(); mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator(bubbleBarLocation); mBubbleBarLocationAnimator.start(); } }); mBubbleBarLocationAnimator.start(); } private AnimatorSet getLocationUpdateFadeOutAnimator() { private Animator getLocationUpdateFadeOutAnimator(BubbleBarLocation bubbleBarLocation) { final float shift = getResources().getDisplayMetrics().widthPixels * FADE_OUT_ANIM_POSITION_SHIFT; final float tx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift; final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); final float tx = getTranslationX() + (onLeft ? shift : -shift); ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, TRANSLATION_X, tx) .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS); Loading @@ -431,14 +412,31 @@ public class BubbleBarView extends FrameLayout { return animatorSet; } private Animator getLocationUpdateFadeInAnimator() { private Animator getLocationUpdateFadeInAnimator(BubbleBarLocation animatedLocation) { final float shift = getResources().getDisplayMetrics().widthPixels * FADE_IN_ANIM_POSITION_SHIFT; final float startTx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift; final boolean onLeft = animatedLocation.isOnLeft(isLayoutRtl()); final float startTx; final float finalTx; if (animatedLocation == mBubbleBarLocation) { // Animated location matches layout location. finalTx = 0; } else { // We are animating in to a transient location, need to move the bar accordingly. finalTx = getDistanceFromOtherSide() * (onLeft ? -1 : 1); } if (onLeft) { // Bar will be shown on the left side. Start point is shifted right. startTx = finalTx + shift; } else { // Bar will be shown on the right side. Start point is shifted left. startTx = finalTx - shift; } ValueAnimator positionAnim = new SpringAnimationBuilder(getContext()) .setStartValue(startTx) .setEndValue(0) .setEndValue(finalTx) .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY) .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS) .build(this, VIEW_TRANSLATE_X); Loading Loading @@ -547,7 +545,7 @@ public class BubbleBarView extends FrameLayout { * Updates the z order, positions, and badge visibility of the bubble views in the bar based * on the expanded state. */ private void updateChildrenRenderNodeProperties() { private void updateChildrenRenderNodeProperties(BubbleBarLocation bubbleBarLocation) { final float widthState = (float) mWidthAnimator.getAnimatedValue(); final float currentWidth = getWidth(); final float expandedWidth = expandedWidth(); Loading @@ -555,7 +553,7 @@ public class BubbleBarView extends FrameLayout { int bubbleCount = getChildCount(); final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f; final boolean animate = getVisibility() == VISIBLE; final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl()); final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl()); // elevation state is opposite to widthState - when expanded all icons are flat float elevationState = (1 - widthState); for (int i = 0; i < bubbleCount; i++) { Loading Loading @@ -613,8 +611,9 @@ public class BubbleBarView extends FrameLayout { } // update the arrow position final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed(); final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded(); final float collapsedArrowPosition = arrowPositionForSelectedWhenCollapsed( bubbleBarLocation); final float expandedArrowPosition = arrowPositionForSelectedWhenExpanded(bubbleBarLocation); final float interpolatedWidth = widthState * (expandedWidth - collapsedWidth) + collapsedWidth; final float arrowPosition; Loading Loading @@ -661,7 +660,7 @@ public class BubbleBarView extends FrameLayout { addViewInLayout(child, i, child.getLayoutParams()); } } updateChildrenRenderNodeProperties(); updateChildrenRenderNodeProperties(mBubbleBarLocation); } } Loading Loading @@ -702,7 +701,7 @@ public class BubbleBarView extends FrameLayout { return; } // Find the center of the bubble when it's expanded, set the arrow position to it. final float tx = arrowPositionForSelectedWhenExpanded(); final float tx = arrowPositionForSelectedWhenExpanded(mBubbleBarLocation); final float currentArrowPosition = mBubbleBarBackground.getArrowPositionX(); if (tx == currentArrowPosition) { // arrow position remains unchanged Loading @@ -727,10 +726,10 @@ public class BubbleBarView extends FrameLayout { } } private float arrowPositionForSelectedWhenExpanded() { private float arrowPositionForSelectedWhenExpanded(BubbleBarLocation bubbleBarLocation) { final int index = indexOfChild(mSelectedBubbleView); final int bubblePosition; if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) { if (bubbleBarLocation.isOnLeft(isLayoutRtl())) { // Bubble positions are reversed. First bubble is on the right. bubblePosition = getChildCount() - index - 1; } else { Loading @@ -740,10 +739,10 @@ public class BubbleBarView extends FrameLayout { + mIconSize / 2f; } private float arrowPositionForSelectedWhenCollapsed() { private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) { final int index = indexOfChild(mSelectedBubbleView); final int bubblePosition; if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) { if (bubbleBarLocation.isOnLeft(isLayoutRtl())) { // Bubble positions are reversed. First bubble may be shifted, if there are more // bubbles than the current bubble and overflow. bubblePosition = index == 0 && getChildCount() > 2 ? 1 : 0; Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +11 −2 Original line number Diff line number Diff line Loading @@ -215,8 +215,17 @@ public class BubbleBarViewController { /** * Update bar {@link BubbleBarLocation} */ public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) { mBarView.setBubbleBarLocation(bubbleBarLocation, animate); public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mBarView.setBubbleBarLocation(bubbleBarLocation); } /** * Animate bubble bar to the given location. The location change is transient. It does not * update the state of the bubble bar. * To update bubble bar pinned location, use {@link #setBubbleBarLocation(BubbleBarLocation)}. */ public void animateBubbleBarLocation(BubbleBarLocation bubbleBarLocation) { mBarView.animateToBubbleBarLocation(bubbleBarLocation); } /** Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java +5 −5 Original line number Diff line number Diff line Loading @@ -110,25 +110,25 @@ public class BubbleDragAnimator { /** * Animates the dragged bubble movement back to the initial position. * * @param initialPosition the position to animate to * @param restingPosition the position to animate to * @param velocity the initial velocity to use for the spring animation * @param endActions gets called when the animation completes or gets cancelled */ public void animateToInitialState(@NonNull PointF initialPosition, @NonNull PointF velocity, public void animateToRestingState(@NonNull PointF restingPosition, @NonNull PointF velocity, @Nullable Runnable endActions) { mBubbleAnimator.cancel(); mBubbleAnimator .spring(DynamicAnimation.SCALE_X, 1f) .spring(DynamicAnimation.SCALE_Y, 1f) .spring(DynamicAnimation.TRANSLATION_X, initialPosition.x, velocity.x, .spring(DynamicAnimation.TRANSLATION_X, restingPosition.x, velocity.x, mTranslationConfig) .spring(DynamicAnimation.TRANSLATION_Y, initialPosition.y, velocity.y, .spring(DynamicAnimation.TRANSLATION_Y, restingPosition.y, velocity.y, mTranslationConfig) .addEndListener((View target, @NonNull FloatPropertyCompat<? super View> property, boolean wasFling, boolean canceled, float finalValue, float finalVelocity, boolean allRelevantPropertyAnimationsEnded) -> { if (canceled || allRelevantPropertyAnimationsEnded) { resetAnimatedViews(initialPosition); resetAnimatedViews(restingPosition); if (endActions != null) { endActions.run(); } Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java +31 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.wm.shell.common.bubbles.BaseBubblePinController.LocationChangeListener; import com.android.wm.shell.common.bubbles.BubbleBarLocation; /** * Controls bubble bar drag interactions. Loading @@ -37,6 +39,7 @@ import com.android.launcher3.taskbar.TaskbarActivityContext; */ public class BubbleDragController { private final TaskbarActivityContext mActivity; private BubbleBarController mBubbleBarController; private BubbleBarViewController mBubbleBarViewController; private BubbleDismissController mBubbleDismissController; private BubbleBarPinController mBubbleBarPinController; Loading @@ -51,11 +54,10 @@ public class BubbleDragController { * controllers may still be waiting for init(). */ public void init(@NonNull BubbleControllers bubbleControllers) { mBubbleBarController = bubbleControllers.bubbleBarController; mBubbleBarViewController = bubbleControllers.bubbleBarViewController; mBubbleDismissController = bubbleControllers.bubbleDismissController; mBubbleBarPinController = bubbleControllers.bubbleBarPinController; mBubbleBarPinController.setListener( bubbleControllers.bubbleBarController::updateBubbleBarLocation); mBubbleDismissController.setListener( stuck -> mBubbleBarPinController.setDropTargetHidden(stuck)); } Loading Loading @@ -96,6 +98,17 @@ public class BubbleDragController { PointF initialRelativePivot = new PointF(); bubbleBarView.setOnTouchListener(new BubbleTouchListener() { @Nullable private BubbleBarLocation mReleasedLocation; private final LocationChangeListener mLocationChangeListener = new LocationChangeListener() { @Override public void onRelease(@NonNull BubbleBarLocation location) { mReleasedLocation = location; } }; @Override protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) { if (bubbleBarView.isExpanded()) return false; Loading @@ -104,6 +117,7 @@ public class BubbleDragController { @Override void onDragStart() { mBubbleBarPinController.setListener(mLocationChangeListener); initialRelativePivot.set(bubbleBarView.getRelativePivotX(), bubbleBarView.getRelativePivotY()); // By default the bubble bar view pivot is in bottom right corner, while dragging Loading Loading @@ -134,13 +148,17 @@ public class BubbleDragController { // Restoring the initial pivot for the bubble bar view bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y); bubbleBarView.setIsDragging(false); mBubbleBarController.updateBubbleBarLocation(mReleasedLocation); } @Override protected PointF getRestingPosition() { PointF restingPosition = super.getRestingPosition(); bubbleBarView.adjustRelativeRestingPosition(restingPosition); return restingPosition; if (mReleasedLocation == null || mReleasedLocation == bubbleBarView.getBubbleBarLocation()) { return getInitialPosition(); } return bubbleBarView.getBubbleBarDragReleaseTranslation(getInitialPosition(), mReleasedLocation); } }); } Loading Loading @@ -228,6 +246,13 @@ public class BubbleDragController { protected void onDragDismiss() { } /** * Get the initial position of the view when drag started */ protected PointF getInitialPosition() { return mViewInitialPosition; } /** * Get the resting position of the view when drag is released */ Loading Loading @@ -362,7 +387,7 @@ public class BubbleDragController { mAnimator.animateDismiss(mViewInitialPosition, onComplete); } else { onDragRelease(); mAnimator.animateToInitialState(getRestingPosition(), getCurrentVelocity(), mAnimator.animateToRestingState(getRestingPosition(), getCurrentVelocity(), onComplete); } mBubbleDismissController.hideDismissView(); Loading