diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 9d65d28b21b47..05ebbba4e955a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -422,14 +422,6 @@ public class Bubble implements BubbleViewProvider { } } - @Override - public void setExpandedContentAlpha(float alpha) { - if (mExpandedView != null) { - mExpandedView.setAlpha(alpha); - mExpandedView.setTaskViewAlpha(alpha); - } - } - /** * Set visibility of bubble in the expanded state. * diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 9dafefebf62b0..ea04fb6daa9fe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -144,7 +144,6 @@ public class BubbleController { private BubbleLogger mLogger; private BubbleData mBubbleData; - private View mBubbleScrim; @Nullable private BubbleStackView mStackView; private BubbleIconFactory mBubbleIconFactory; private BubblePositioner mBubblePositioner; @@ -1372,8 +1371,9 @@ public class BubbleController { private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedTaskListener { @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { + mBubblePositioner.setImeVisible(imeVisible, imeHeight); if (mStackView != null) { - mStackView.onImeVisibilityChanged(imeVisible, imeHeight); + mStackView.animateForIme(imeVisible); } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 7d7bfb2a92a33..a87aad4261a69 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -398,6 +398,7 @@ public class BubbleExpandedView extends LinearLayout { updatePointerView(); } + /** Updates the size and visuals of the pointer. **/ private void updatePointerView() { LayoutParams lp = (LayoutParams) mPointerView.getLayoutParams(); if (mCurrentPointer == mLeftPointer || mCurrentPointer == mRightPointer) { @@ -524,9 +525,8 @@ public class BubbleExpandedView extends LinearLayout { if (mTaskView != null) { mTaskView.setAlpha(alpha); } - if (mManageButton != null && mManageButton.getVisibility() == View.VISIBLE) { - mManageButton.setAlpha(alpha); - } + mPointerView.setAlpha(alpha); + setAlpha(alpha); } /** @@ -545,6 +545,7 @@ public class BubbleExpandedView extends LinearLayout { mIsContentVisible = visibility; if (mTaskView != null && !mIsAlphaAnimating) { mTaskView.setAlpha(visibility ? 1f : 0f); + mPointerView.setAlpha(visibility ? 1f : 0f); } } @@ -689,7 +690,7 @@ public class BubbleExpandedView extends LinearLayout { * the bubble if showing vertically. * @param onLeft whether the stack was on the left side of the screen when expanded. */ - public void setPointerPosition(float bubblePosition, boolean onLeft) { + public void setPointerPosition(float bubblePosition, boolean onLeft, boolean animate) { // Pointer gets drawn in the padding final boolean showVertically = mPositioner.showBubblesVertically(); final float paddingLeft = (showVertically && onLeft) @@ -710,6 +711,8 @@ public class BubbleExpandedView extends LinearLayout { : pointerPosition; // Post because we need the width of the view post(() -> { + mCurrentPointer = showVertically ? onLeft ? mLeftPointer : mRightPointer : mTopPointer; + updatePointerView(); float pointerY; float pointerX; if (showVertically) { @@ -721,11 +724,13 @@ public class BubbleExpandedView extends LinearLayout { pointerY = mPointerOverlap; pointerX = bubbleCenter - (mPointerWidth / 2f); } - mPointerView.setTranslationY(pointerY); - mPointerView.setTranslationX(pointerX); - mCurrentPointer = showVertically ? onLeft ? mLeftPointer : mRightPointer : mTopPointer; - updatePointerView(); - mPointerView.setVisibility(VISIBLE); + if (animate) { + mPointerView.animate().translationX(pointerX).translationY(pointerY).start(); + } else { + mPointerView.setTranslationY(pointerY); + mPointerView.setTranslationX(pointerX); + mPointerView.setVisibility(VISIBLE); + } }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt index 705a12a5e65b5..0c3a6b2dbd842 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt @@ -154,10 +154,6 @@ class BubbleOverflow( return dotPath } - override fun setExpandedContentAlpha(alpha: Float) { - expandedView?.alpha = alpha - } - override fun setTaskViewVisibility(visible: Boolean) { // Overflow does not have a TaskView. } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java index 306224bd316c8..127d5a8a9966e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java @@ -70,13 +70,16 @@ public class BubblePositioner { private Context mContext; private WindowManager mWindowManager; - private Rect mPositionRect; private Rect mScreenRect; private @Surface.Rotation int mRotation = Surface.ROTATION_0; private Insets mInsets; + private boolean mImeVisible; + private int mImeHeight; + private boolean mIsLargeScreen; + + private Rect mPositionRect; private int mDefaultMaxBubbles; private int mMaxBubbles; - private int mBubbleSize; private int mSpacingBetweenBubbles; @@ -98,7 +101,6 @@ public class BubblePositioner { private PointF mRestingStackPosition; private int[] mPaddings = new int[4]; - private boolean mIsLargeScreen; private boolean mShowingInTaskbar; private @TaskbarPosition int mTaskbarPosition = TASKBAR_POSITION_NONE; private int mTaskbarIconSize; @@ -302,6 +304,17 @@ public class BubblePositioner { return mMaxBubbles; } + /** The height for the IME if it's visible. **/ + public int getImeHeight() { + return mImeVisible ? mImeHeight : 0; + } + + /** Sets whether the IME is visible. **/ + public void setImeVisible(boolean visible, int height) { + mImeVisible = visible; + mImeHeight = height; + } + /** * Calculates the padding for the bubble expanded view. * @@ -357,7 +370,7 @@ public class BubblePositioner { } /** Gets the y position of the expanded view if it was top-aligned. */ - private float getExpandedViewYTopAligned() { + public float getExpandedViewYTopAligned() { final int top = getAvailableRect().top; if (showBubblesVertically()) { return top - mPointerWidth + mExpandedViewPadding; @@ -366,10 +379,6 @@ public class BubblePositioner { } } - public float getExpandedBubblesY() { - return getAvailableRect().top + mExpandedViewPadding; - } - /** * Calculate the maximum height the expanded view can be depending on where it's placed on * the screen and the size of the elements around it (e.g. padding, pointer, manage button). @@ -464,18 +473,21 @@ public class BubblePositioner { : bubblePosition + (normalizedSize / 2f) - mPointerWidth; } + private int getExpandedStackSize(int numberOfBubbles) { + return (numberOfBubbles * mBubbleSize) + + ((numberOfBubbles - 1) * mSpacingBetweenBubbles); + } + /** * Returns the position of the bubble on-screen when the stack is expanded. * * @param index the index of the bubble in the stack. - * @param numberOfBubbles the total number of bubbles in the stack. - * @param onLeftEdge whether the stack would rest on the left edge of the screen when collapsed. - * @return the x, y position of the bubble on-screen when the stack is expanded. + * @param state state information about the stack to help with calculations. + * @return the position of the bubble on-screen when the stack is expanded. */ - public PointF getExpandedBubbleXY(int index, int numberOfBubbles, boolean onLeftEdge) { + public PointF getExpandedBubbleXY(int index, BubbleStackView.StackViewState state) { final float positionInRow = index * (mBubbleSize + mSpacingBetweenBubbles); - final float expandedStackSize = (numberOfBubbles * mBubbleSize) - + ((numberOfBubbles - 1) * mSpacingBetweenBubbles); + final float expandedStackSize = getExpandedStackSize(state.numberOfBubbles); final float centerPosition = showBubblesVertically() ? mPositionRect.centerY() : mPositionRect.centerX(); @@ -491,16 +503,65 @@ public class BubblePositioner { int right = mIsLargeScreen ? mPositionRect.right - mExpandedViewLargeScreenInset + mExpandedViewPadding : mPositionRect.right - mBubbleSize; - x = onLeftEdge + x = state.onLeft ? left : right; } else { y = mPositionRect.top + mExpandedViewPadding; x = rowStart + positionInRow; } + + if (showBubblesVertically() && mImeVisible) { + return new PointF(x, getExpandedBubbleYForIme(index, state.numberOfBubbles)); + } return new PointF(x, y); } + /** + * Returns the position of the bubble on-screen when the stack is expanded and the IME + * is showing. + * + * @param index the index of the bubble in the stack. + * @param numberOfBubbles the total number of bubbles in the stack. + * @return y position of the bubble on-screen when the stack is expanded. + */ + private float getExpandedBubbleYForIme(int index, int numberOfBubbles) { + final float top = getAvailableRect().top + mExpandedViewPadding; + if (!showBubblesVertically()) { + // Showing horizontally: align to top + return top; + } + + // Showing vertically: might need to translate the bubbles above the IME. + // Subtract spacing here to provide a margin between top of IME and bottom of bubble row. + final float bottomInset = getImeHeight() + mInsets.bottom - (mSpacingBetweenBubbles * 2); + final float expandedStackSize = getExpandedStackSize(numberOfBubbles); + final float centerPosition = showBubblesVertically() + ? mPositionRect.centerY() + : mPositionRect.centerX(); + final float rowBottom = centerPosition + (expandedStackSize / 2f); + final float rowTop = centerPosition - (expandedStackSize / 2f); + float rowTopForIme = rowTop; + if (rowBottom > bottomInset) { + // We overlap with IME, must shift the bubbles + float translationY = rowBottom - bottomInset; + rowTopForIme = Math.max(rowTop - translationY, top); + if (rowTop - translationY < top) { + // Even if we shift the bubbles, they will still overlap with the IME. + // Hide the overflow for a lil more space: + final float expandedStackSizeNoO = getExpandedStackSize(numberOfBubbles - 1); + final float centerPositionNoO = showBubblesVertically() + ? mPositionRect.centerY() + : mPositionRect.centerX(); + final float rowBottomNoO = centerPositionNoO + (expandedStackSizeNoO / 2f); + final float rowTopNoO = centerPositionNoO - (expandedStackSizeNoO / 2f); + translationY = rowBottomNoO - bottomInset; + rowTopForIme = rowTopNoO - translationY; + } + } + return rowTopForIme + (index * (mBubbleSize + mSpacingBetweenBubbles)); + } + /** * @return the width of the bubble flyout (message originating from the bubble). */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 5bc6128d6c9ec..9d0dd3c7fcdb6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -28,6 +28,8 @@ import static com.android.wm.shell.bubbles.BubblePositioner.NUM_VISIBLE_WHEN_RES import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.ContentResolver; @@ -188,6 +190,7 @@ public class BubbleStackView extends FrameLayout }; private final BubbleController mBubbleController; private final BubbleData mBubbleData; + private StackViewState mStackViewState = new StackViewState(); private final ValueAnimator mDismissBubbleAnimator; @@ -246,7 +249,6 @@ public class BubbleStackView extends FrameLayout private int mBubbleTouchPadding; private int mExpandedViewPadding; private int mCornerRadius; - private int mImeOffset; @Nullable private BubbleViewProvider mExpandedBubble; private boolean mIsExpanded; @@ -757,7 +759,6 @@ public class BubbleStackView extends FrameLayout mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size); mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation); mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding); - mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset); mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding); int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation); @@ -779,7 +780,7 @@ public class BubbleStackView extends FrameLayout this::animateShadows /* onStackAnimationFinished */, mPositioner); mExpandedAnimationController = new ExpandedAnimationController(mPositioner, - onBubbleAnimatedOut); + onBubbleAnimatedOut, this); mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER; // Force LTR by default since most of the Bubbles UI is positioned manually by the user, or @@ -890,7 +891,7 @@ public class BubbleStackView extends FrameLayout // Re-draw bubble row and pointer for new orientation. beforeExpandedViewAnimation(); updateOverflowVisibility(); - updatePointerPosition(); + updatePointerPosition(false /* forIme */); mExpandedAnimationController.expandFromStack(() -> { afterExpandedViewAnimation(); } /* after */); @@ -968,7 +969,8 @@ public class BubbleStackView extends FrameLayout }); mExpandedViewAlphaAnimator.addUpdateListener(valueAnimator -> { if (mExpandedBubble != null) { - mExpandedBubble.setExpandedContentAlpha((float) valueAnimator.getAnimatedValue()); + mExpandedBubble.getExpandedView().setTaskViewAlpha( + (float) valueAnimator.getAnimatedValue()); } }); @@ -1558,7 +1560,7 @@ public class BubbleStackView extends FrameLayout } else { bubble.cleanupViews(); } - updatePointerPosition(); + updatePointerPosition(false /* forIme */); updateExpandedView(); logBubbleEvent(bubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__DISMISSED); return; @@ -1599,7 +1601,7 @@ public class BubbleStackView extends FrameLayout .map(b -> b.getIconView()).collect(Collectors.toList()); mStackAnimationController.animateReorder(bubbleViews, reorder); } - updatePointerPosition(); + updatePointerPosition(false /* forIme */); } /** @@ -1670,7 +1672,6 @@ public class BubbleStackView extends FrameLayout private void showNewlySelectedBubble(BubbleViewProvider bubbleToSelect) { final BubbleViewProvider previouslySelected = mExpandedBubble; mExpandedBubble = bubbleToSelect; - updatePointerPosition(); if (mIsExpanded) { hideCurrentInputMethod(); @@ -1762,6 +1763,7 @@ public class BubbleStackView extends FrameLayout * not. */ void hideCurrentInputMethod() { + mPositioner.setImeVisible(false, 0); mBubbleController.hideCurrentInputMethod(); } @@ -1864,7 +1866,7 @@ public class BubbleStackView extends FrameLayout updateBadges(false /* setBadgeForCollapsedStack */); mBubbleContainer.setActiveController(mExpandedAnimationController); updateOverflowVisibility(); - updatePointerPosition(); + updatePointerPosition(false /* forIme */); mExpandedAnimationController.expandFromStack(() -> { if (mIsExpanded && mExpandedBubble.getExpandedView() != null) { maybeShowManageEdu(); @@ -1876,8 +1878,7 @@ public class BubbleStackView extends FrameLayout } else { index = getBubbleIndex(mExpandedBubble); } - PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleContainer.getChildCount(), - mStackOnLeftOrWillBe); + PointF p = mPositioner.getExpandedBubbleXY(index, getState()); final float translationY = mPositioner.getExpandedViewY(mExpandedBubble, mPositioner.showBubblesVertically() ? p.y : p.x); mExpandedViewContainer.setTranslationX(0f); @@ -1928,7 +1929,7 @@ public class BubbleStackView extends FrameLayout mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix); if (mExpandedBubble.getExpandedView() != null) { - mExpandedBubble.setExpandedContentAlpha(0f); + mExpandedBubble.getExpandedView().setTaskViewAlpha(0f); // We'll be starting the alpha animation after a slight delay, so set this flag early // here. @@ -2011,8 +2012,7 @@ public class BubbleStackView extends FrameLayout index = mBubbleData.getBubbles().indexOf(mExpandedBubble); } // Value the bubble is animating from (back into the stack). - final PointF p = mPositioner.getExpandedBubbleXY(index, - mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); + final PointF p = mPositioner.getExpandedBubbleXY(index, getState()); if (mPositioner.showBubblesVertically()) { float pivotX; float pivotY = p.y + mBubbleSize / 2f; @@ -2109,7 +2109,7 @@ public class BubbleStackView extends FrameLayout PointF p = mPositioner.getExpandedBubbleXY(isOverflow ? mBubbleContainer.getChildCount() - 1 : mBubbleData.getBubbles().indexOf(mExpandedBubble), - mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); + getState()); mExpandedViewContainer.setAlpha(1f); mExpandedViewContainer.setVisibility(View.VISIBLE); @@ -2187,9 +2187,20 @@ public class BubbleStackView extends FrameLayout } } - /** Moves the bubbles out of the way if they're going to be over the keyboard. */ - public void onImeVisibilityChanged(boolean visible, int height) { - mStackAnimationController.setImeHeight(visible ? height + mImeOffset : 0); + /** + * Updates the stack based for IME changes. When collapsed it'll move the stack if it + * overlaps where they IME would be. When expanded it'll shift the expanded bubbles + * if they might overlap with the IME (this only happens for large screens). + */ + public void animateForIme(boolean visible) { + if ((mIsExpansionAnimating || mIsBubbleSwitchAnimating) && mIsExpanded) { + // This will update the animation so the bubbles move to position for the IME + mExpandedAnimationController.expandFromStack(() -> { + updatePointerPosition(false /* forIme */); + afterExpandedViewAnimation(); + } /* after */); + return; + } if (!mIsExpanded && getBubbleCount() > 0) { final float stackDestinationY = @@ -2208,9 +2219,20 @@ public class BubbleStackView extends FrameLayout FLYOUT_IME_ANIMATION_SPRING_CONFIG) .start(); } - } else if (mIsExpanded && mExpandedBubble != null - && mExpandedBubble.getExpandedView() != null) { + } else if (mPositioner.showBubblesVertically() && mIsExpanded + && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) { mExpandedBubble.getExpandedView().setImeVisible(visible); + List animList = new ArrayList(); + for (int i = 0; i < mBubbleContainer.getChildCount(); i++) { + View child = mBubbleContainer.getChildAt(i); + float transY = mPositioner.getExpandedBubbleXY(i, getState()).y; + ObjectAnimator anim = ObjectAnimator.ofFloat(child, TRANSLATION_Y, transY); + animList.add(anim); + } + updatePointerPosition(true /* forIme */); + AnimatorSet set = new AnimatorSet(); + set.playTogether(animList); + set.start(); } } @@ -2514,7 +2536,7 @@ public class BubbleStackView extends FrameLayout // Account for the IME in the touchable region so that the touchable region of the // Bubble window doesn't obscure the IME. The touchable region affects which areas // of the screen can be excluded by lower windows (IME is just above the embedded task) - outRect.bottom -= (int) mStackAnimationController.getImeHeight(); + outRect.bottom -= mPositioner.getImeHeight(); } if (mFlyout.getVisibility() == View.VISIBLE) { @@ -2773,13 +2795,13 @@ public class BubbleStackView extends FrameLayout } if (mExpandedBubble != null && mExpandedBubble.getExpandedView() != null) { PointF p = mPositioner.getExpandedBubbleXY(getBubbleIndex(mExpandedBubble), - mBubbleContainer.getChildCount(), mStackOnLeftOrWillBe); + getState()); mExpandedViewContainer.setTranslationY(mPositioner.getExpandedViewY(mExpandedBubble, mPositioner.showBubblesVertically() ? p.y : p.x)); mExpandedViewContainer.setTranslationX(0f); mExpandedBubble.getExpandedView().updateView( mExpandedViewContainer.getLocationOnScreen()); - updatePointerPosition(); + updatePointerPosition(false /* forIme */); } mStackOnLeftOrWillBe = mStackAnimationController.isStackOnLeftSide(); @@ -2850,7 +2872,13 @@ public class BubbleStackView extends FrameLayout } } - private void updatePointerPosition() { + /** + * Updates the position of the pointer based on the expanded bubble. + * + * @param forIme whether the position is being updated due to the ime appearing, in this case + * the pointer is animated to the location. + */ + private void updatePointerPosition(boolean forIme) { if (mExpandedBubble == null || mExpandedBubble.getExpandedView() == null) { return; } @@ -2858,13 +2886,12 @@ public class BubbleStackView extends FrameLayout if (index == -1) { return; } - PointF bubblePosition = mPositioner.getExpandedBubbleXY(index, - mBubbleContainer.getChildCount(), - mStackOnLeftOrWillBe); - mExpandedBubble.getExpandedView().setPointerPosition(mPositioner.showBubblesVertically() - ? bubblePosition.y - : bubblePosition.x, - mStackOnLeftOrWillBe); + PointF position = mPositioner.getExpandedBubbleXY(index, getState()); + float bubblePosition = mPositioner.showBubblesVertically() + ? position.y + : position.x; + mExpandedBubble.getExpandedView().setPointerPosition(bubblePosition, + mStackOnLeftOrWillBe, forIme /* animate */); } /** @@ -2947,6 +2974,26 @@ public class BubbleStackView extends FrameLayout return bubbles; } + /** @return the current stack state. */ + public StackViewState getState() { + mStackViewState.numberOfBubbles = mBubbleContainer.getChildCount(); + mStackViewState.selectedIndex = getBubbleIndex(mExpandedBubble); + mStackViewState.onLeft = mStackOnLeftOrWillBe; + return mStackViewState; + } + + /** + * Holds some commonly queried information about the stack. + */ + public static class StackViewState { + // Number of bubbles (including the overflow itself) in the stack. + public int numberOfBubbles; + // The selected index if the stack is expanded. + public int selectedIndex; + // Whether the stack is resting on the left or right side of the screen when collapsed. + public boolean onLeft; + } + /** * Representation of stack position that uses relative properties rather than absolute * coordinates. This is used to maintain similar stack positions across configuration changes. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java index 38b3ba9dfda00..7e552826e94ae 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewProvider.java @@ -28,12 +28,6 @@ import androidx.annotation.Nullable; public interface BubbleViewProvider { @Nullable BubbleExpandedView getExpandedView(); - /** - * Sets the alpha of the expanded view content. This will be applied to both the expanded view - * container itself (the manage button, etc.) as well as the TaskView within it. - */ - void setExpandedContentAlpha(float alpha); - /** * Sets whether the contents of the bubble's TaskView should be visible. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java index c32be98866cf7..f0f78748e343a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationController.java @@ -21,7 +21,6 @@ import static com.android.wm.shell.bubbles.BubblePositioner.NUM_VISIBLE_WHEN_RES import android.content.res.Resources; import android.graphics.Path; import android.graphics.PointF; -import android.graphics.Rect; import android.view.View; import androidx.annotation.NonNull; @@ -33,6 +32,7 @@ import com.android.wm.shell.R; import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.animation.PhysicsAnimator; import com.android.wm.shell.bubbles.BubblePositioner; +import com.android.wm.shell.bubbles.BubbleStackView; import com.android.wm.shell.common.magnetictarget.MagnetizedObject; import com.google.android.collect.Sets; @@ -124,12 +124,15 @@ public class ExpandedAnimationController private BubblePositioner mPositioner; + private BubbleStackView mBubbleStackView; + public ExpandedAnimationController(BubblePositioner positioner, - Runnable onBubbleAnimatedOutAction) { + Runnable onBubbleAnimatedOutAction, BubbleStackView stackView) { mPositioner = positioner; updateResources(); mOnBubbleAnimatedOutAction = onBubbleAnimatedOutAction; mCollapsePoint = mPositioner.getDefaultStartPosition(); + mBubbleStackView = stackView; } /** @@ -239,10 +242,7 @@ public class ExpandedAnimationController final Path path = new Path(); path.moveTo(bubble.getTranslationX(), bubble.getTranslationY()); - boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint); - final PointF p = mPositioner.getExpandedBubbleXY(index, - mLayout.getChildCount(), - onLeft); + final PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleStackView.getState()); if (expanding) { // If we're expanding, first draw a line from the bubble's current position to where // it'll end up @@ -364,7 +364,7 @@ public class ExpandedAnimationController bubbleView.setTranslationY(y); } - final float expandedY = mPositioner.getExpandedBubblesY(); + final float expandedY = mPositioner.getExpandedViewYTopAligned(); final boolean draggedOutEnough = y > expandedY + mBubbleSizePx || y < expandedY - mBubbleSizePx; if (draggedOutEnough != mBubbleDraggedOutEnough) { @@ -410,8 +410,7 @@ public class ExpandedAnimationController return; } final int index = mLayout.indexOfChild(bubbleView); - final PointF p = mPositioner.getExpandedBubbleXY(index, mLayout.getChildCount(), - mPositioner.isStackOnLeft(mCollapsePoint)); + final PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleStackView.getState()); animationForChildAtIndex(index) .position(p.x, p.y) .withPositionStartVelocities(velX, velY) @@ -429,16 +428,6 @@ public class ExpandedAnimationController updateBubblePositions(); } - /** - * Animates the bubbles to the y position. Used in response to IME showing. - */ - public void updateYPosition(Runnable after) { - if (mLayout == null) return; - animationsForChildrenFromIndex( - 0, (i, anim) -> anim.translationY(mPositioner.getExpandedBubblesY())) - .startAll(after); - } - /** Description of current animation controller state. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("ExpandedAnimationController state:"); @@ -496,36 +485,33 @@ public class ExpandedAnimationController startOrUpdatePathAnimation(false /* expanding */); } else { boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint); - final PointF p = mPositioner.getExpandedBubbleXY(index, - mLayout.getChildCount(), - onLeft); + final PointF p = mPositioner.getExpandedBubbleXY(index, mBubbleStackView.getState()); if (mPositioner.showBubblesVertically()) { child.setTranslationY(p.y); } else { child.setTranslationX(p.x); } - if (!mPreparingToCollapse) { - // Only animate if we're not collapsing as that animation will handle placing the + + if (mPreparingToCollapse) { + // Don't animate if we're collapsing, as that animation will handle placing the // new bubble in the stacked position. - if (mPositioner.showBubblesVertically()) { - Rect availableRect = mPositioner.getAvailableRect(); - float fromX = onLeft - ? -mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR - : availableRect.right + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; - animationForChild(child) - .translationX(fromX, p.y) - .start(); - } else { - // Only animate if we're not collapsing as that animation will handle placing - // the new bubble in the stacked position. - float fromY = mPositioner.getExpandedBubblesY() - mBubbleSizePx - * ANIMATE_TRANSLATION_FACTOR; - animationForChild(child) - .translationY(fromY, p.y) - .start(); - } - updateBubblePositions(); + return; } + + if (mPositioner.showBubblesVertically()) { + float fromX = onLeft + ? p.x - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR + : p.x + mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; + animationForChild(child) + .translationX(fromX, p.y) + .start(); + } else { + float fromY = p.y - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR; + animationForChild(child) + .translationY(fromY, p.y) + .start(); + } + updateBubblePositions(); } } @@ -572,7 +558,6 @@ public class ExpandedAnimationController if (mAnimatingExpand || mAnimatingCollapse) { return; } - boolean onLeft = mPositioner.isStackOnLeft(mCollapsePoint); for (int i = 0; i < mLayout.getChildCount(); i++) { final View bubble = mLayout.getChildAt(i); @@ -582,7 +567,7 @@ public class ExpandedAnimationController return; } - final PointF p = mPositioner.getExpandedBubbleXY(i, mLayout.getChildCount(), onLeft); + final PointF p = mPositioner.getExpandedBubbleXY(i, mBubbleStackView.getState()); animationForChild(bubble) .translationX(p.x) .translationY(p.y) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java index 9a08190675b63..60b64333114e4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/StackAnimationController.java @@ -127,9 +127,6 @@ public class StackAnimationController extends /** Whether or not the stack's start position has been set. */ private boolean mStackMovedToStartPosition = false; - /** The height of the most recently visible IME. */ - private float mImeHeight = 0f; - /** * The Y position of the stack before the IME became visible, or {@link Float#MIN_VALUE} if the * IME is not visible or the user moved the stack since the IME became visible. @@ -173,7 +170,7 @@ public class StackAnimationController extends */ private boolean mSpringToTouchOnNextMotionEvent = false; - /** Horizontal offset of bubbles in the stack. */ + /** Offset of bubbles in the stack (i.e. how much they overlap). */ private float mStackOffset; /** Offset between stack y and animation y for bubble swap. */ private float mSwapAnimationOffset; @@ -521,16 +518,6 @@ public class StackAnimationController extends removeEndActionForProperty(DynamicAnimation.TRANSLATION_Y); } - /** Save the current IME height so that we know where the stack bounds should be. */ - public void setImeHeight(int imeHeight) { - mImeHeight = imeHeight; - } - - /** Returns the current IME height that the stack is offset by. */ - public float getImeHeight() { - return mImeHeight; - } - /** * Animates the stack either away from the newly visible IME, or back to its original position * due to the IME going away. @@ -589,11 +576,14 @@ public class StackAnimationController extends */ public RectF getAllowableStackPositionRegion() { final RectF allowableRegion = new RectF(mPositioner.getAvailableRect()); + final int imeHeight = mPositioner.getImeHeight(); + final float bottomPadding = getBubbleCount() > 1 + ? mBubblePaddingTop + mStackOffset + : mBubblePaddingTop; allowableRegion.left -= mBubbleOffscreen; allowableRegion.top += mBubblePaddingTop; allowableRegion.right += mBubbleOffscreen - mBubbleSize; - allowableRegion.bottom -= mBubblePaddingTop + mBubbleSize - + (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f); + allowableRegion.bottom -= imeHeight + bottomPadding + mBubbleSize; return allowableRegion; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java index 9732a8890e0ef..2b9bdce45a6c0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/animation/ExpandedAnimationControllerTest.java @@ -16,10 +16,12 @@ package com.android.wm.shell.bubbles.animation; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static org.mockito.Mockito.when; import android.annotation.SuppressLint; import android.content.res.Configuration; @@ -37,6 +39,7 @@ import androidx.test.filters.SmallTest; import com.android.wm.shell.R; import com.android.wm.shell.bubbles.BubblePositioner; +import com.android.wm.shell.bubbles.BubbleStackView; import org.junit.Before; import org.junit.Ignore; @@ -56,18 +59,22 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC private int mStackOffset; private PointF mExpansionPoint; private BubblePositioner mPositioner; + private BubbleStackView.StackViewState mStackViewState; @SuppressLint("VisibleForTests") @Before public void setUp() throws Exception { super.setUp(); + BubbleStackView stackView = mock(BubbleStackView.class); + when(stackView.getState()).thenReturn(getStackViewState()); mPositioner = new BubblePositioner(getContext(), mock(WindowManager.class)); mPositioner.updateInternal(Configuration.ORIENTATION_PORTRAIT, Insets.of(0, 0, 0, 0), new Rect(0, 0, mDisplayWidth, mDisplayHeight)); mExpandedController = new ExpandedAnimationController(mPositioner, - mOnBubbleAnimatedOutAction); + mOnBubbleAnimatedOutAction, + stackView); spyOn(mExpandedController); addOneMoreThanBubbleLimitBubbles(); @@ -78,6 +85,13 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC mExpansionPoint = new PointF(100, 100); } + public BubbleStackView.StackViewState getStackViewState() { + mStackViewState.numberOfBubbles = mLayout.getChildCount(); + mStackViewState.selectedIndex = 0; + mStackViewState.onLeft = mPositioner.isStackOnLeft(mExpansionPoint); + return mStackViewState; + } + @Test @Ignore public void testExpansionAndCollapse() throws InterruptedException { @@ -141,12 +155,10 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC /** Check that children are in the correct positions for being expanded. */ private void testBubblesInCorrectExpandedPositions() { - boolean onLeft = mPositioner.isStackOnLeft(mExpansionPoint); // Check all the visible bubbles to see if they're in the right place. for (int i = 0; i < mLayout.getChildCount(); i++) { PointF expectedPosition = mPositioner.getExpandedBubbleXY(i, - mLayout.getChildCount(), - onLeft); + getStackViewState()); assertEquals(expectedPosition.x, mLayout.getChildAt(i).getTranslationX(), 2f);