Merge "Center-align bubble row" into qt-dev
am: aa21a4a71c
Change-Id: I1ace3d53da854bee0408c22589c267f3659494ef
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user