Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +28 −22 Original line number Diff line number Diff line Loading @@ -699,6 +699,7 @@ public class BubbleStackView extends FrameLayout { animateInFlyoutForBubble(bubble); requestUpdate(); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED); updatePointerPosition(); } // via BubbleData.Listener Loading @@ -714,6 +715,7 @@ public class BubbleStackView extends FrameLayout { } else { Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble); } updatePointerPosition(); } // via BubbleData.Listener Loading Loading @@ -1538,18 +1540,22 @@ public class BubbleStackView extends FrameLayout { if (DEBUG) { Log.d(TAG, "updatePointerPosition()"); } Bubble expandedBubble = getExpandedBubble(); if (expandedBubble != null) { BubbleView iconView = expandedBubble.iconView; float bubbleLeft = iconView.getTranslationX(); float halfBubbleWidth = (iconView.getWidth() / 2f); if (expandedBubble == null) { return; } int index = getBubbleIndex(expandedBubble); float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index); float halfBubble = mBubbleSize / 2f; // Bubbles live in expanded view container (x includes expanded view padding). // Pointer lives in expanded view, which has padding (x does not include padding). // Remove padding when deriving pointer location from bubbles. float pointerX = bubbleLeft - mExpandedViewPadding + halfBubbleWidth; expandedBubble.expandedView.setPointerPosition((int) pointerX); } float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble - mExpandedViewPadding; expandedBubble.expandedView.setPointerPosition(bubbleCenter); } /** Loading packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +51 −38 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public class ExpandedAnimationController private Point mDisplaySize; /** Size of dismiss target at bottom of screen. */ private float mPipDismissHeight; /** Max number of bubbles shown in row above expanded view.*/ private int mBubblesMaxRendered; /** Whether the dragged-out bubble is in the dismiss target. */ private boolean mIndividualBubbleWithinDismissTarget = false; Loading Loading @@ -112,32 +114,25 @@ public class ExpandedAnimationController mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height); mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered); } /** * Animates expanding the bubbles into a row along the top of the screen. * * @return The y-value to which the bubbles were expanded, in case that's useful. */ public float expandFromStack(PointF collapseTo, Runnable after) { public void expandFromStack(PointF collapseTo, Runnable after) { animationsForChildrenFromIndex( 0, /* startIndex */ new ChildAnimationConfigurator() { // How much to translate the next bubble, so that it is not overlapping the // previous one. float mTranslateNextBubbleXBy = mExpandedViewPadding + mBubblePaddingPx; @Override public void configureAnimationForChildAtIndex( int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) { animation.position(mTranslateNextBubbleXBy, getExpandedY()); mTranslateNextBubbleXBy += mBubbleSizePx + mBubblePaddingPx; animation.position(getBubbleLeft(index), getExpandedY()); } }) .startAll(after); mCollapseToPoint = collapseTo; return getExpandedY(); } /** Animate collapsing the bubbles back to their stacked position. */ Loading Loading @@ -189,9 +184,7 @@ public class ExpandedAnimationController final boolean draggedOutEnough = y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx; if (draggedOutEnough != mBubbleDraggedOutEnough) { animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ draggedOutEnough ? -1 : 0, /* startIndex */ mLayout.indexOfChild(bubbleView) + 1); updateBubblePositions(); mBubbleDraggedOutEnough = draggedOutEnough; } } Loading @@ -200,17 +193,14 @@ public class ExpandedAnimationController public void dismissDraggedOutBubble(Runnable after) { mIndividualBubbleWithinDismissTarget = false; // Fill the space from the soon to be dismissed bubble. animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ -1, /* startIndex */ mLayout.indexOfChild(mBubbleDraggingOut) + 1); animationForChild(mBubbleDraggingOut) .withStiffness(SpringForce.STIFFNESS_HIGH) .scaleX(1.1f) .scaleY(1.1f) .alpha(0f, after) .start(); updateBubblePositions(); } /** Magnets the given bubble to the dismiss target. */ Loading Loading @@ -251,15 +241,13 @@ public class ExpandedAnimationController final int index = mLayout.indexOfChild(bubbleView); animationForChildAtIndex(index) .position(getXForChildAtIndex(index), getExpandedY()) .position(getBubbleLeft(index), getExpandedY()) .withPositionStartVelocities(velX, velY) .start(() -> bubbleView.setTranslationZ(0f) /* after */); animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ 0, /* startIndex */ index + 1); mBubbleDraggingOut = null; mBubbleDraggedOutEnough = false; updateBubblePositions(); } /** Loading Loading @@ -337,8 +325,6 @@ public class ExpandedAnimationController @Override void onChildAdded(View child, int index) { // Pop in from the top. // TODO: Reverse this when bubbles are at the bottom. child.setTranslationX(getXForChildAtIndex(index)); animationForChild(child) Loading @@ -346,7 +332,7 @@ public class ExpandedAnimationController getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */ getExpandedY() /* to */) .start(); animateBubblesAfterIndexToCorrectX(index); updateBubblePositions(); } @Override Loading @@ -367,7 +353,7 @@ public class ExpandedAnimationController } // Animate all the other bubbles to their new positions sans this bubble. animateBubblesAfterIndexToCorrectX(index); updateBubblePositions(); } @Override Loading @@ -383,26 +369,53 @@ public class ExpandedAnimationController .start(() -> super.setChildVisibility(child, index, visibility) /* after */); } /** * Animates the bubbles after the given index to the X position they should be in according to * {@link #getXForChildAtIndex}. */ private void animateBubblesAfterIndexToCorrectX(int start) { for (int i = start; i < mLayout.getChildCount(); i++) { private void updateBubblePositions() { for (int i = 0; i < mLayout.getChildCount(); i++) { final View bubble = mLayout.getChildAt(i); // Don't animate the dragging out bubble, or it'll jump around while being dragged. It // will be snapped to the correct X value after the drag (if it's not dismissed). if (!bubble.equals(mBubbleDraggingOut)) { if (bubble.equals(mBubbleDraggingOut)) { return; } animationForChild(bubble) .translationX(getXForChildAtIndex(i)) .translationX(getBubbleLeft(i)) .start(); } } } /** Returns the appropriate X translation value for a bubble at the given index. */ private float getXForChildAtIndex(int index) { return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * index; } /** * @param index Bubble index in row. * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { float bubbleLeftFromRowLeft = index * (mBubbleSizePx + mBubblePaddingPx); return getRowLeft() + bubbleLeftFromRowLeft; } private float getRowLeft() { if (mLayout == null) { return 0; } int bubbleCount = mLayout.getChildCount(); if (bubbleCount > mBubblesMaxRendered) { // Only shown bubbles are relevant for calculating position. bubbleCount = mBubblesMaxRendered; } // Width calculations. double bubble = bubbleCount * mBubbleSizePx; float gap = (bubbleCount - 1) * mBubblePaddingPx; float row = gap + (float) bubble; float halfRow = row / 2f; float centerScreen = mDisplaySize.x / 2; float rowLeftFromScreenLeft = centerScreen - halfRow; return rowLeftFromScreenLeft; } } packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java +36 −3 Original line number Diff line number Diff line Loading @@ -43,10 +43,14 @@ import org.mockito.Spy; @RunWith(AndroidTestingRunner.class) public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase { private int mDisplayWidth = 500; private int mDisplayHeight = 1000; @Spy private ExpandedAnimationController mExpandedController = new ExpandedAnimationController( new Point(500, 1000) /* displaySize */, 0 /* expandedViewPadding */); new Point(mDisplayWidth, mDisplayHeight) /* displaySize */, 0 /* expandedViewPadding */); private int mStackOffset; private float mBubblePadding; private float mBubbleSize; Loading @@ -58,11 +62,11 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC super.setUp(); addOneMoreThanRenderLimitBubbles(); mLayout.setController(mExpandedController); Resources res = mLayout.getResources(); mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding); mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size); mExpansionPoint = new PointF(100, 100); } Loading Loading @@ -243,7 +247,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC private void testBubblesInCorrectExpandedPositions() { // Check all the visible bubbles to see if they're in the right place. for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) { assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)), assertEquals(getBubbleLeft(i), mLayout.getChildAt(i).getTranslationX(), 2f); assertEquals(mExpandedController.getExpandedY(), Loading @@ -254,4 +258,33 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC } } } /** * @param index Bubble index in row. * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { float bubbleLeftFromRowLeft = index * (mBubbleSize + mBubblePadding); return getRowLeft() + bubbleLeftFromRowLeft; } private float getRowLeft() { if (mLayout == null) { return 0; } int bubbleCount = mLayout.getChildCount(); if (bubbleCount > mMaxRenderedBubbles) { bubbleCount = mMaxRenderedBubbles; } // Width calculations. double bubble = bubbleCount * mBubbleSize; float gap = (bubbleCount - 1) * mBubblePadding; float row = gap + (float) bubble; float halfRow = row / 2f; float centerScreen = mDisplayWidth / 2; float rowLeftFromScreenLeft = centerScreen - halfRow; return rowLeftFromScreenLeft; } } Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +28 −22 Original line number Diff line number Diff line Loading @@ -699,6 +699,7 @@ public class BubbleStackView extends FrameLayout { animateInFlyoutForBubble(bubble); requestUpdate(); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED); updatePointerPosition(); } // via BubbleData.Listener Loading @@ -714,6 +715,7 @@ public class BubbleStackView extends FrameLayout { } else { Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble); } updatePointerPosition(); } // via BubbleData.Listener Loading Loading @@ -1538,18 +1540,22 @@ public class BubbleStackView extends FrameLayout { if (DEBUG) { Log.d(TAG, "updatePointerPosition()"); } Bubble expandedBubble = getExpandedBubble(); if (expandedBubble != null) { BubbleView iconView = expandedBubble.iconView; float bubbleLeft = iconView.getTranslationX(); float halfBubbleWidth = (iconView.getWidth() / 2f); if (expandedBubble == null) { return; } int index = getBubbleIndex(expandedBubble); float bubbleLeftFromScreenLeft = mExpandedAnimationController.getBubbleLeft(index); float halfBubble = mBubbleSize / 2f; // Bubbles live in expanded view container (x includes expanded view padding). // Pointer lives in expanded view, which has padding (x does not include padding). // Remove padding when deriving pointer location from bubbles. float pointerX = bubbleLeft - mExpandedViewPadding + halfBubbleWidth; expandedBubble.expandedView.setPointerPosition((int) pointerX); } float bubbleCenter = bubbleLeftFromScreenLeft + halfBubble - mExpandedViewPadding; expandedBubble.expandedView.setPointerPosition(bubbleCenter); } /** Loading
packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +51 −38 Original line number Diff line number Diff line Loading @@ -63,6 +63,8 @@ public class ExpandedAnimationController private Point mDisplaySize; /** Size of dismiss target at bottom of screen. */ private float mPipDismissHeight; /** Max number of bubbles shown in row above expanded view.*/ private int mBubblesMaxRendered; /** Whether the dragged-out bubble is in the dismiss target. */ private boolean mIndividualBubbleWithinDismissTarget = false; Loading Loading @@ -112,32 +114,25 @@ public class ExpandedAnimationController mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height); mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered); } /** * Animates expanding the bubbles into a row along the top of the screen. * * @return The y-value to which the bubbles were expanded, in case that's useful. */ public float expandFromStack(PointF collapseTo, Runnable after) { public void expandFromStack(PointF collapseTo, Runnable after) { animationsForChildrenFromIndex( 0, /* startIndex */ new ChildAnimationConfigurator() { // How much to translate the next bubble, so that it is not overlapping the // previous one. float mTranslateNextBubbleXBy = mExpandedViewPadding + mBubblePaddingPx; @Override public void configureAnimationForChildAtIndex( int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) { animation.position(mTranslateNextBubbleXBy, getExpandedY()); mTranslateNextBubbleXBy += mBubbleSizePx + mBubblePaddingPx; animation.position(getBubbleLeft(index), getExpandedY()); } }) .startAll(after); mCollapseToPoint = collapseTo; return getExpandedY(); } /** Animate collapsing the bubbles back to their stacked position. */ Loading Loading @@ -189,9 +184,7 @@ public class ExpandedAnimationController final boolean draggedOutEnough = y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx; if (draggedOutEnough != mBubbleDraggedOutEnough) { animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ draggedOutEnough ? -1 : 0, /* startIndex */ mLayout.indexOfChild(bubbleView) + 1); updateBubblePositions(); mBubbleDraggedOutEnough = draggedOutEnough; } } Loading @@ -200,17 +193,14 @@ public class ExpandedAnimationController public void dismissDraggedOutBubble(Runnable after) { mIndividualBubbleWithinDismissTarget = false; // Fill the space from the soon to be dismissed bubble. animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ -1, /* startIndex */ mLayout.indexOfChild(mBubbleDraggingOut) + 1); animationForChild(mBubbleDraggingOut) .withStiffness(SpringForce.STIFFNESS_HIGH) .scaleX(1.1f) .scaleY(1.1f) .alpha(0f, after) .start(); updateBubblePositions(); } /** Magnets the given bubble to the dismiss target. */ Loading Loading @@ -251,15 +241,13 @@ public class ExpandedAnimationController final int index = mLayout.indexOfChild(bubbleView); animationForChildAtIndex(index) .position(getXForChildAtIndex(index), getExpandedY()) .position(getBubbleLeft(index), getExpandedY()) .withPositionStartVelocities(velX, velY) .start(() -> bubbleView.setTranslationZ(0f) /* after */); animateStackByBubbleWidthsStartingFrom( /* numBubbleWidths */ 0, /* startIndex */ index + 1); mBubbleDraggingOut = null; mBubbleDraggedOutEnough = false; updateBubblePositions(); } /** Loading Loading @@ -337,8 +325,6 @@ public class ExpandedAnimationController @Override void onChildAdded(View child, int index) { // Pop in from the top. // TODO: Reverse this when bubbles are at the bottom. child.setTranslationX(getXForChildAtIndex(index)); animationForChild(child) Loading @@ -346,7 +332,7 @@ public class ExpandedAnimationController getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */ getExpandedY() /* to */) .start(); animateBubblesAfterIndexToCorrectX(index); updateBubblePositions(); } @Override Loading @@ -367,7 +353,7 @@ public class ExpandedAnimationController } // Animate all the other bubbles to their new positions sans this bubble. animateBubblesAfterIndexToCorrectX(index); updateBubblePositions(); } @Override Loading @@ -383,26 +369,53 @@ public class ExpandedAnimationController .start(() -> super.setChildVisibility(child, index, visibility) /* after */); } /** * Animates the bubbles after the given index to the X position they should be in according to * {@link #getXForChildAtIndex}. */ private void animateBubblesAfterIndexToCorrectX(int start) { for (int i = start; i < mLayout.getChildCount(); i++) { private void updateBubblePositions() { for (int i = 0; i < mLayout.getChildCount(); i++) { final View bubble = mLayout.getChildAt(i); // Don't animate the dragging out bubble, or it'll jump around while being dragged. It // will be snapped to the correct X value after the drag (if it's not dismissed). if (!bubble.equals(mBubbleDraggingOut)) { if (bubble.equals(mBubbleDraggingOut)) { return; } animationForChild(bubble) .translationX(getXForChildAtIndex(i)) .translationX(getBubbleLeft(i)) .start(); } } } /** Returns the appropriate X translation value for a bubble at the given index. */ private float getXForChildAtIndex(int index) { return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * index; } /** * @param index Bubble index in row. * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { float bubbleLeftFromRowLeft = index * (mBubbleSizePx + mBubblePaddingPx); return getRowLeft() + bubbleLeftFromRowLeft; } private float getRowLeft() { if (mLayout == null) { return 0; } int bubbleCount = mLayout.getChildCount(); if (bubbleCount > mBubblesMaxRendered) { // Only shown bubbles are relevant for calculating position. bubbleCount = mBubblesMaxRendered; } // Width calculations. double bubble = bubbleCount * mBubbleSizePx; float gap = (bubbleCount - 1) * mBubblePaddingPx; float row = gap + (float) bubble; float halfRow = row / 2f; float centerScreen = mDisplaySize.x / 2; float rowLeftFromScreenLeft = centerScreen - halfRow; return rowLeftFromScreenLeft; } }
packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java +36 −3 Original line number Diff line number Diff line Loading @@ -43,10 +43,14 @@ import org.mockito.Spy; @RunWith(AndroidTestingRunner.class) public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase { private int mDisplayWidth = 500; private int mDisplayHeight = 1000; @Spy private ExpandedAnimationController mExpandedController = new ExpandedAnimationController( new Point(500, 1000) /* displaySize */, 0 /* expandedViewPadding */); new Point(mDisplayWidth, mDisplayHeight) /* displaySize */, 0 /* expandedViewPadding */); private int mStackOffset; private float mBubblePadding; private float mBubbleSize; Loading @@ -58,11 +62,11 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC super.setUp(); addOneMoreThanRenderLimitBubbles(); mLayout.setController(mExpandedController); Resources res = mLayout.getResources(); mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding); mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size); mExpansionPoint = new PointF(100, 100); } Loading Loading @@ -243,7 +247,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC private void testBubblesInCorrectExpandedPositions() { // Check all the visible bubbles to see if they're in the right place. for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) { assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)), assertEquals(getBubbleLeft(i), mLayout.getChildAt(i).getTranslationX(), 2f); assertEquals(mExpandedController.getExpandedY(), Loading @@ -254,4 +258,33 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC } } } /** * @param index Bubble index in row. * @return Bubble left x from left edge of screen. */ public float getBubbleLeft(int index) { float bubbleLeftFromRowLeft = index * (mBubbleSize + mBubblePadding); return getRowLeft() + bubbleLeftFromRowLeft; } private float getRowLeft() { if (mLayout == null) { return 0; } int bubbleCount = mLayout.getChildCount(); if (bubbleCount > mMaxRenderedBubbles) { bubbleCount = mMaxRenderedBubbles; } // Width calculations. double bubble = bubbleCount * mBubbleSize; float gap = (bubbleCount - 1) * mBubblePadding; float row = gap + (float) bubble; float halfRow = row / 2f; float centerScreen = mDisplayWidth / 2; float rowLeftFromScreenLeft = centerScreen - halfRow; return rowLeftFromScreenLeft; } }