Merge "Remember the stack position, including across configuration changes." into rvc-qpr-dev
This commit is contained in:
@@ -82,6 +82,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.internal.statusbar.NotificationVisibility;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.bubbles.animation.StackAnimationController;
|
||||
import com.android.systemui.bubbles.dagger.BubbleModule;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
@@ -168,6 +169,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
||||
@Nullable private BubbleStackView mStackView;
|
||||
private BubbleIconFactory mBubbleIconFactory;
|
||||
|
||||
/**
|
||||
* The relative position of the stack when we removed it and nulled it out. If the stack is
|
||||
* re-created, it will re-appear at this position.
|
||||
*/
|
||||
@Nullable private BubbleStackView.RelativeStackPosition mPositionFromRemovedStack;
|
||||
|
||||
// Tracks the id of the current (foreground) user.
|
||||
private int mCurrentUserId;
|
||||
// Saves notification keys of active bubbles when users are switched.
|
||||
@@ -718,6 +725,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
||||
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
|
||||
mSysUiState, this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
|
||||
this::hideCurrentInputMethod);
|
||||
mStackView.setStackStartPosition(mPositionFromRemovedStack);
|
||||
mStackView.addView(mBubbleScrim);
|
||||
if (mExpandListener != null) {
|
||||
mStackView.setExpandListener(mExpandListener);
|
||||
@@ -787,6 +795,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
||||
try {
|
||||
mAddedToWindowManager = false;
|
||||
if (mStackView != null) {
|
||||
mPositionFromRemovedStack = mStackView.getRelativeStackPosition();
|
||||
mWindowManager.removeView(mStackView);
|
||||
mStackView.removeView(mBubbleScrim);
|
||||
mStackView = null;
|
||||
|
||||
@@ -258,13 +258,8 @@ public class BubbleStackView extends FrameLayout
|
||||
|
||||
/** Layout change listener that moves the stack to the nearest valid position on rotation. */
|
||||
private OnLayoutChangeListener mOrientationChangedListener;
|
||||
/** Whether the stack was on the left side of the screen prior to rotation. */
|
||||
private boolean mWasOnLeftBeforeRotation = false;
|
||||
/**
|
||||
* How far down the screen the stack was before rotation, in terms of percentage of the way down
|
||||
* the allowable region. Defaults to -1 if not set.
|
||||
*/
|
||||
private float mVerticalPosPercentBeforeRotation = -1;
|
||||
|
||||
@Nullable private RelativeStackPosition mRelativeStackPositionBeforeRotation;
|
||||
|
||||
private int mMaxBubbles;
|
||||
private int mBubbleSize;
|
||||
@@ -967,9 +962,10 @@ public class BubbleStackView extends FrameLayout
|
||||
mExpandedViewContainer.setTranslationY(getExpandedViewY());
|
||||
mExpandedViewContainer.setAlpha(1f);
|
||||
}
|
||||
if (mVerticalPosPercentBeforeRotation >= 0) {
|
||||
mStackAnimationController.moveStackToSimilarPositionAfterRotation(
|
||||
mWasOnLeftBeforeRotation, mVerticalPosPercentBeforeRotation);
|
||||
if (mRelativeStackPositionBeforeRotation != null) {
|
||||
mStackAnimationController.setStackPosition(
|
||||
mRelativeStackPositionBeforeRotation);
|
||||
mRelativeStackPositionBeforeRotation = null;
|
||||
}
|
||||
removeOnLayoutChangeListener(mOrientationChangedListener);
|
||||
};
|
||||
@@ -1231,13 +1227,7 @@ public class BubbleStackView extends FrameLayout
|
||||
com.android.internal.R.dimen.status_bar_height);
|
||||
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
|
||||
|
||||
final RectF allowablePos = mStackAnimationController.getAllowableStackPositionRegion();
|
||||
mWasOnLeftBeforeRotation = mStackAnimationController.isStackOnLeftSide();
|
||||
mVerticalPosPercentBeforeRotation =
|
||||
(mStackAnimationController.getStackPosition().y - allowablePos.top)
|
||||
/ (allowablePos.bottom - allowablePos.top);
|
||||
mVerticalPosPercentBeforeRotation =
|
||||
Math.max(0f, Math.min(1f, mVerticalPosPercentBeforeRotation));
|
||||
mRelativeStackPositionBeforeRotation = mStackAnimationController.getRelativeStackPosition();
|
||||
addOnLayoutChangeListener(mOrientationChangedListener);
|
||||
hideFlyoutImmediate();
|
||||
|
||||
@@ -1506,7 +1496,7 @@ public class BubbleStackView extends FrameLayout
|
||||
if (getBubbleCount() == 0 && mShouldShowUserEducation) {
|
||||
// Override the default stack position if we're showing user education.
|
||||
mStackAnimationController.setStackPosition(
|
||||
mStackAnimationController.getDefaultStartPosition());
|
||||
mStackAnimationController.getStartPosition());
|
||||
}
|
||||
|
||||
if (getBubbleCount() == 0) {
|
||||
@@ -1721,7 +1711,7 @@ public class BubbleStackView extends FrameLayout
|
||||
// Post so we have height of mUserEducationView
|
||||
mUserEducationView.post(() -> {
|
||||
final int viewHeight = mUserEducationView.getHeight();
|
||||
PointF stackPosition = mStackAnimationController.getDefaultStartPosition();
|
||||
PointF stackPosition = mStackAnimationController.getStartPosition();
|
||||
final float translationY = stackPosition.y + (mBubbleSize / 2) - (viewHeight / 2);
|
||||
mUserEducationView.setTranslationY(translationY);
|
||||
mUserEducationView.animate()
|
||||
@@ -2877,10 +2867,18 @@ public class BubbleStackView extends FrameLayout
|
||||
.floatValue();
|
||||
}
|
||||
|
||||
public void setStackStartPosition(RelativeStackPosition position) {
|
||||
mStackAnimationController.setStackStartPosition(position);
|
||||
}
|
||||
|
||||
public PointF getStackPosition() {
|
||||
return mStackAnimationController.getStackPosition();
|
||||
}
|
||||
|
||||
public RelativeStackPosition getRelativeStackPosition() {
|
||||
return mStackAnimationController.getRelativeStackPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the bubble UI event.
|
||||
*
|
||||
@@ -2944,4 +2942,47 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
return bubbles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Representation of stack position that uses relative properties rather than absolute
|
||||
* coordinates. This is used to maintain similar stack positions across configuration changes.
|
||||
*/
|
||||
public static class RelativeStackPosition {
|
||||
/** Whether to place the stack at the leftmost allowed position. */
|
||||
private boolean mOnLeft;
|
||||
|
||||
/**
|
||||
* How far down the vertically allowed region to place the stack. For example, if the stack
|
||||
* allowed region is between y = 100 and y = 1100 and this is 0.2f, we'll place the stack at
|
||||
* 100 + (0.2f * 1000) = 300.
|
||||
*/
|
||||
private float mVerticalOffsetPercent;
|
||||
|
||||
public RelativeStackPosition(boolean onLeft, float verticalOffsetPercent) {
|
||||
mOnLeft = onLeft;
|
||||
mVerticalOffsetPercent = clampVerticalOffsetPercent(verticalOffsetPercent);
|
||||
}
|
||||
|
||||
/** Constructs a relative position given a region and a point in that region. */
|
||||
public RelativeStackPosition(PointF position, RectF region) {
|
||||
mOnLeft = position.x < region.width() / 2;
|
||||
mVerticalOffsetPercent =
|
||||
clampVerticalOffsetPercent((position.y - region.top) / region.height());
|
||||
}
|
||||
|
||||
/** Ensures that the offset percent is between 0f and 1f. */
|
||||
private float clampVerticalOffsetPercent(float offsetPercent) {
|
||||
return Math.max(0f, Math.min(1f, offsetPercent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an allowable stack position region, returns the point within that region
|
||||
* represented by this relative position.
|
||||
*/
|
||||
public PointF getAbsolutePositionInRegion(RectF region) {
|
||||
return new PointF(
|
||||
mOnLeft ? region.left : region.right,
|
||||
region.top + mVerticalOffsetPercent * region.height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringForce;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.bubbles.BubbleStackView;
|
||||
import com.android.systemui.util.FloatingContentCoordinator;
|
||||
import com.android.systemui.util.animation.PhysicsAnimator;
|
||||
import com.android.systemui.util.magnetictarget.MagnetizedObject;
|
||||
@@ -125,6 +126,9 @@ public class StackAnimationController extends
|
||||
*/
|
||||
private Rect mAnimatingToBounds = new Rect();
|
||||
|
||||
/** Initial starting location for the stack. */
|
||||
@Nullable private BubbleStackView.RelativeStackPosition mStackStartPosition;
|
||||
|
||||
/** Whether or not the stack's start position has been set. */
|
||||
private boolean mStackMovedToStartPosition = false;
|
||||
|
||||
@@ -431,21 +435,6 @@ public class StackAnimationController extends
|
||||
return stackPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the stack in response to rotation. We keep it in the most similar position by keeping
|
||||
* it on the same side, and positioning it the same percentage of the way down the screen
|
||||
* (taking status bar/nav bar into account by using the allowable region's height).
|
||||
*/
|
||||
public void moveStackToSimilarPositionAfterRotation(boolean wasOnLeft, float verticalPercent) {
|
||||
final RectF allowablePos = getAllowableStackPositionRegion();
|
||||
final float allowableRegionHeight = allowablePos.bottom - allowablePos.top;
|
||||
|
||||
final float x = wasOnLeft ? allowablePos.left : allowablePos.right;
|
||||
final float y = (allowableRegionHeight * verticalPercent) + allowablePos.top;
|
||||
|
||||
setStackPosition(new PointF(x, y));
|
||||
}
|
||||
|
||||
/** Description of current animation controller state. */
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
pw.println("StackAnimationController state:");
|
||||
@@ -815,7 +804,7 @@ public class StackAnimationController extends
|
||||
} else {
|
||||
// When all children are removed ensure stack position is sane
|
||||
setStackPosition(mRestingStackPosition == null
|
||||
? getDefaultStartPosition()
|
||||
? getStartPosition()
|
||||
: mRestingStackPosition);
|
||||
|
||||
// Remove the stack from the coordinator since we don't have any bubbles and aren't
|
||||
@@ -868,7 +857,7 @@ public class StackAnimationController extends
|
||||
mLayout.setVisibility(View.INVISIBLE);
|
||||
mLayout.post(() -> {
|
||||
setStackPosition(mRestingStackPosition == null
|
||||
? getDefaultStartPosition()
|
||||
? getStartPosition()
|
||||
: mRestingStackPosition);
|
||||
mStackMovedToStartPosition = true;
|
||||
mLayout.setVisibility(View.VISIBLE);
|
||||
@@ -938,15 +927,47 @@ public class StackAnimationController extends
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the default stack position, which is on the top left. */
|
||||
public PointF getDefaultStartPosition() {
|
||||
boolean isRtl = mLayout != null
|
||||
&& mLayout.getResources().getConfiguration().getLayoutDirection()
|
||||
== View.LAYOUT_DIRECTION_RTL;
|
||||
return new PointF(isRtl
|
||||
? getAllowableStackPositionRegion().right
|
||||
: getAllowableStackPositionRegion().left,
|
||||
getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
|
||||
public void setStackPosition(BubbleStackView.RelativeStackPosition position) {
|
||||
setStackPosition(position.getAbsolutePositionInRegion(getAllowableStackPositionRegion()));
|
||||
}
|
||||
|
||||
public BubbleStackView.RelativeStackPosition getRelativeStackPosition() {
|
||||
return new BubbleStackView.RelativeStackPosition(
|
||||
mStackPosition, getAllowableStackPositionRegion());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the starting position for the stack, where it will be located when the first bubble is
|
||||
* added.
|
||||
*/
|
||||
public void setStackStartPosition(BubbleStackView.RelativeStackPosition position) {
|
||||
mStackStartPosition = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the starting stack position. If {@link #setStackStartPosition} was called, this will
|
||||
* return that position - otherwise, a reasonable default will be returned.
|
||||
*/
|
||||
@Nullable public PointF getStartPosition() {
|
||||
if (mLayout == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mStackStartPosition == null) {
|
||||
// Start on the left if we're in LTR, right otherwise.
|
||||
final boolean startOnLeft =
|
||||
mLayout.getResources().getConfiguration().getLayoutDirection()
|
||||
!= View.LAYOUT_DIRECTION_RTL;
|
||||
|
||||
final float startingVerticalOffset = mLayout.getResources().getDimensionPixelOffset(
|
||||
R.dimen.bubble_stack_starting_offset_y);
|
||||
|
||||
mStackStartPosition = new BubbleStackView.RelativeStackPosition(
|
||||
startOnLeft,
|
||||
startingVerticalOffset / getAllowableStackPositionRegion().height());
|
||||
}
|
||||
|
||||
return mStackStartPosition.getAbsolutePositionInRegion(getAllowableStackPositionRegion());
|
||||
}
|
||||
|
||||
private boolean isStackPositionSet() {
|
||||
|
||||
Reference in New Issue
Block a user