Merge "Center-align bubble row" into qt-dev

am: aa21a4a71c

Change-Id: I1ace3d53da854bee0408c22589c267f3659494ef
This commit is contained in:
Lyn Han
2019-05-28 09:55:05 -07:00
committed by android-build-merger
3 changed files with 115 additions and 63 deletions

View File

@@ -237,16 +237,16 @@ public class BubbleStackView extends FrameLayout {
private ViewClippingUtil.ClippingParameters mClippingParameters = private ViewClippingUtil.ClippingParameters mClippingParameters =
new ViewClippingUtil.ClippingParameters() { new ViewClippingUtil.ClippingParameters() {
@Override @Override
public boolean shouldFinish(View view) { public boolean shouldFinish(View view) {
return false; return false;
} }
@Override @Override
public boolean isClippingEnablingAllowed(View view) { public boolean isClippingEnablingAllowed(View view) {
return !mIsExpanded; return !mIsExpanded;
} }
}; };
/** Float property that 'drags' the flyout. */ /** Float property that 'drags' the flyout. */
private final FloatPropertyCompat mFlyoutCollapseProperty = private final FloatPropertyCompat mFlyoutCollapseProperty =
@@ -291,7 +291,7 @@ public class BubbleStackView extends FrameLayout {
private boolean mSuppressFlyout = false; private boolean mSuppressFlyout = false;
public BubbleStackView(Context context, BubbleData data, public BubbleStackView(Context context, BubbleData data,
@Nullable SurfaceSynchronizer synchronizer) { @Nullable SurfaceSynchronizer synchronizer) {
super(context); super(context);
mBubbleData = data; mBubbleData = data;
@@ -699,6 +699,7 @@ public class BubbleStackView extends FrameLayout {
animateInFlyoutForBubble(bubble); animateInFlyoutForBubble(bubble);
requestUpdate(); requestUpdate();
logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
updatePointerPosition();
} }
// via BubbleData.Listener // via BubbleData.Listener
@@ -714,6 +715,7 @@ public class BubbleStackView extends FrameLayout {
} else { } else {
Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble); Log.d(TAG, "was asked to remove Bubble, but didn't find the view! " + bubble);
} }
updatePointerPosition();
} }
// via BubbleData.Listener // via BubbleData.Listener
@@ -1073,8 +1075,8 @@ public class BubbleStackView extends FrameLayout {
(overscrollingPastDot ? collapsePercent - 1f : collapsePercent * -1) (overscrollingPastDot ? collapsePercent - 1f : collapsePercent * -1)
* (overscrollingLeft ? -1 : 1) * (overscrollingLeft ? -1 : 1)
* (mFlyout.getWidth() / (FLYOUT_OVERSCROLL_ATTENUATION_FACTOR * (mFlyout.getWidth() / (FLYOUT_OVERSCROLL_ATTENUATION_FACTOR
// Attenuate the smaller dot less than the larger flyout. // Attenuate the smaller dot less than the larger flyout.
/ (overscrollingPastDot ? 2 : 1))); / (overscrollingPastDot ? 2 : 1)));
} }
mFlyout.setTranslationX(mFlyout.getRestingTranslationX() + overscrollTranslation); mFlyout.setTranslationX(mFlyout.getRestingTranslationX() + overscrollTranslation);
@@ -1530,18 +1532,22 @@ public class BubbleStackView extends FrameLayout {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "updatePointerPosition()"); Log.d(TAG, "updatePointerPosition()");
} }
Bubble expandedBubble = getExpandedBubble();
if (expandedBubble != null) {
BubbleView iconView = expandedBubble.iconView;
float bubbleLeft = iconView.getTranslationX();
float halfBubbleWidth = (iconView.getWidth() / 2f);
// Bubbles live in expanded view container (x includes expanded view padding). Bubble expandedBubble = getExpandedBubble();
// Pointer lives in expanded view, which has padding (x does not include padding). if (expandedBubble == null) {
// Remove padding when deriving pointer location from bubbles. return;
float pointerX = bubbleLeft - mExpandedViewPadding + halfBubbleWidth;
expandedBubble.expandedView.setPointerPosition((int) pointerX);
} }
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 bubbleCenter = bubbleLeftFromScreenLeft + halfBubble - mExpandedViewPadding;
expandedBubble.expandedView.setPointerPosition(bubbleCenter);
} }
/** /**

View File

@@ -63,6 +63,8 @@ public class ExpandedAnimationController
private Point mDisplaySize; private Point mDisplaySize;
/** Size of dismiss target at bottom of screen. */ /** Size of dismiss target at bottom of screen. */
private float mPipDismissHeight; 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. */ /** Whether the dragged-out bubble is in the dismiss target. */
private boolean mIndividualBubbleWithinDismissTarget = false; private boolean mIndividualBubbleWithinDismissTarget = false;
@@ -112,32 +114,25 @@ public class ExpandedAnimationController
mStatusBarHeight = mStatusBarHeight =
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_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. * 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( animationsForChildrenFromIndex(
0, /* startIndex */ 0, /* startIndex */
new ChildAnimationConfigurator() { new ChildAnimationConfigurator() {
// How much to translate the next bubble, so that it is not overlapping the
// previous one.
float mTranslateNextBubbleXBy = mExpandedViewPadding + mBubblePaddingPx;
@Override @Override
public void configureAnimationForChildAtIndex( public void configureAnimationForChildAtIndex(
int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) { int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) {
animation.position(mTranslateNextBubbleXBy, getExpandedY()); animation.position(getBubbleLeft(index), getExpandedY());
mTranslateNextBubbleXBy += mBubbleSizePx + mBubblePaddingPx;
} }
}) })
.startAll(after); .startAll(after);
mCollapseToPoint = collapseTo; mCollapseToPoint = collapseTo;
return getExpandedY();
} }
/** Animate collapsing the bubbles back to their stacked position. */ /** Animate collapsing the bubbles back to their stacked position. */
@@ -189,9 +184,7 @@ public class ExpandedAnimationController
final boolean draggedOutEnough = final boolean draggedOutEnough =
y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx; y > getExpandedY() + mBubbleSizePx || y < getExpandedY() - mBubbleSizePx;
if (draggedOutEnough != mBubbleDraggedOutEnough) { if (draggedOutEnough != mBubbleDraggedOutEnough) {
animateStackByBubbleWidthsStartingFrom( updateBubblePositions();
/* numBubbleWidths */ draggedOutEnough ? -1 : 0,
/* startIndex */ mLayout.indexOfChild(bubbleView) + 1);
mBubbleDraggedOutEnough = draggedOutEnough; mBubbleDraggedOutEnough = draggedOutEnough;
} }
} }
@@ -200,17 +193,14 @@ public class ExpandedAnimationController
public void dismissDraggedOutBubble(Runnable after) { public void dismissDraggedOutBubble(Runnable after) {
mIndividualBubbleWithinDismissTarget = false; mIndividualBubbleWithinDismissTarget = false;
// Fill the space from the soon to be dismissed bubble.
animateStackByBubbleWidthsStartingFrom(
/* numBubbleWidths */ -1,
/* startIndex */ mLayout.indexOfChild(mBubbleDraggingOut) + 1);
animationForChild(mBubbleDraggingOut) animationForChild(mBubbleDraggingOut)
.withStiffness(SpringForce.STIFFNESS_HIGH) .withStiffness(SpringForce.STIFFNESS_HIGH)
.scaleX(1.1f) .scaleX(1.1f)
.scaleY(1.1f) .scaleY(1.1f)
.alpha(0f, after) .alpha(0f, after)
.start(); .start();
updateBubblePositions();
} }
/** Magnets the given bubble to the dismiss target. */ /** Magnets the given bubble to the dismiss target. */
@@ -251,15 +241,13 @@ public class ExpandedAnimationController
final int index = mLayout.indexOfChild(bubbleView); final int index = mLayout.indexOfChild(bubbleView);
animationForChildAtIndex(index) animationForChildAtIndex(index)
.position(getXForChildAtIndex(index), getExpandedY()) .position(getBubbleLeft(index), getExpandedY())
.withPositionStartVelocities(velX, velY) .withPositionStartVelocities(velX, velY)
.start(() -> bubbleView.setTranslationZ(0f) /* after */); .start(() -> bubbleView.setTranslationZ(0f) /* after */);
animateStackByBubbleWidthsStartingFrom(
/* numBubbleWidths */ 0, /* startIndex */ index + 1);
mBubbleDraggingOut = null; mBubbleDraggingOut = null;
mBubbleDraggedOutEnough = false; mBubbleDraggedOutEnough = false;
updateBubblePositions();
} }
/** /**
@@ -337,8 +325,6 @@ public class ExpandedAnimationController
@Override @Override
void onChildAdded(View child, int index) { void onChildAdded(View child, int index) {
// Pop in from the top.
// TODO: Reverse this when bubbles are at the bottom.
child.setTranslationX(getXForChildAtIndex(index)); child.setTranslationX(getXForChildAtIndex(index));
animationForChild(child) animationForChild(child)
@@ -346,7 +332,7 @@ public class ExpandedAnimationController
getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */ getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
getExpandedY() /* to */) getExpandedY() /* to */)
.start(); .start();
animateBubblesAfterIndexToCorrectX(index); updateBubblePositions();
} }
@Override @Override
@@ -367,7 +353,7 @@ public class ExpandedAnimationController
} }
// Animate all the other bubbles to their new positions sans this bubble. // Animate all the other bubbles to their new positions sans this bubble.
animateBubblesAfterIndexToCorrectX(index); updateBubblePositions();
} }
@Override @Override
@@ -383,21 +369,18 @@ public class ExpandedAnimationController
.start(() -> super.setChildVisibility(child, index, visibility) /* after */); .start(() -> super.setChildVisibility(child, index, visibility) /* after */);
} }
/** private void updateBubblePositions() {
* Animates the bubbles after the given index to the X position they should be in according to for (int i = 0; i < mLayout.getChildCount(); i++) {
* {@link #getXForChildAtIndex}.
*/
private void animateBubblesAfterIndexToCorrectX(int start) {
for (int i = start; i < mLayout.getChildCount(); i++) {
final View bubble = mLayout.getChildAt(i); final View bubble = mLayout.getChildAt(i);
// Don't animate the dragging out bubble, or it'll jump around while being dragged. It // 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). // will be snapped to the correct X value after the drag (if it's not dismissed).
if (!bubble.equals(mBubbleDraggingOut)) { if (bubble.equals(mBubbleDraggingOut)) {
animationForChild(bubble) return;
.translationX(getXForChildAtIndex(i))
.start();
} }
animationForChild(bubble)
.translationX(getBubbleLeft(i))
.start();
} }
} }
@@ -405,4 +388,34 @@ public class ExpandedAnimationController
private float getXForChildAtIndex(int index) { private float getXForChildAtIndex(int index) {
return mBubblePaddingPx + (mBubbleSizePx + mBubblePaddingPx) * 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;
}
} }

View File

@@ -43,10 +43,14 @@ import org.mockito.Spy;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase { public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase {
private int mDisplayWidth = 500;
private int mDisplayHeight = 1000;
@Spy @Spy
private ExpandedAnimationController mExpandedController = private ExpandedAnimationController mExpandedController =
new ExpandedAnimationController( new ExpandedAnimationController(
new Point(500, 1000) /* displaySize */, 0 /* expandedViewPadding */); new Point(mDisplayWidth, mDisplayHeight) /* displaySize */,
0 /* expandedViewPadding */);
private int mStackOffset; private int mStackOffset;
private float mBubblePadding; private float mBubblePadding;
private float mBubbleSize; private float mBubbleSize;
@@ -58,11 +62,11 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
super.setUp(); super.setUp();
addOneMoreThanRenderLimitBubbles(); addOneMoreThanRenderLimitBubbles();
mLayout.setController(mExpandedController); mLayout.setController(mExpandedController);
Resources res = mLayout.getResources(); Resources res = mLayout.getResources();
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset); mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding); mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size); mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mExpansionPoint = new PointF(100, 100); mExpansionPoint = new PointF(100, 100);
} }
@@ -243,7 +247,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
private void testBubblesInCorrectExpandedPositions() { private void testBubblesInCorrectExpandedPositions() {
// Check all the visible bubbles to see if they're in the right place. // 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++) { for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) {
assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)), assertEquals(getBubbleLeft(i),
mLayout.getChildAt(i).getTranslationX(), mLayout.getChildAt(i).getTranslationX(),
2f); 2f);
assertEquals(mExpandedController.getExpandedY(), assertEquals(mExpandedController.getExpandedY(),
@@ -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;
}
} }