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.IStatusBarService;
|
||||||
import com.android.internal.statusbar.NotificationVisibility;
|
import com.android.internal.statusbar.NotificationVisibility;
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
|
import com.android.systemui.bubbles.animation.StackAnimationController;
|
||||||
import com.android.systemui.bubbles.dagger.BubbleModule;
|
import com.android.systemui.bubbles.dagger.BubbleModule;
|
||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
import com.android.systemui.model.SysUiState;
|
import com.android.systemui.model.SysUiState;
|
||||||
@@ -168,6 +169,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
@Nullable private BubbleStackView mStackView;
|
@Nullable private BubbleStackView mStackView;
|
||||||
private BubbleIconFactory mBubbleIconFactory;
|
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.
|
// Tracks the id of the current (foreground) user.
|
||||||
private int mCurrentUserId;
|
private int mCurrentUserId;
|
||||||
// Saves notification keys of active bubbles when users are switched.
|
// Saves notification keys of active bubbles when users are switched.
|
||||||
@@ -718,6 +725,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
|
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
|
||||||
mSysUiState, this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
|
mSysUiState, this::onAllBubblesAnimatedOut, this::onImeVisibilityChanged,
|
||||||
this::hideCurrentInputMethod);
|
this::hideCurrentInputMethod);
|
||||||
|
mStackView.setStackStartPosition(mPositionFromRemovedStack);
|
||||||
mStackView.addView(mBubbleScrim);
|
mStackView.addView(mBubbleScrim);
|
||||||
if (mExpandListener != null) {
|
if (mExpandListener != null) {
|
||||||
mStackView.setExpandListener(mExpandListener);
|
mStackView.setExpandListener(mExpandListener);
|
||||||
@@ -787,6 +795,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|
|||||||
try {
|
try {
|
||||||
mAddedToWindowManager = false;
|
mAddedToWindowManager = false;
|
||||||
if (mStackView != null) {
|
if (mStackView != null) {
|
||||||
|
mPositionFromRemovedStack = mStackView.getRelativeStackPosition();
|
||||||
mWindowManager.removeView(mStackView);
|
mWindowManager.removeView(mStackView);
|
||||||
mStackView.removeView(mBubbleScrim);
|
mStackView.removeView(mBubbleScrim);
|
||||||
mStackView = null;
|
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. */
|
/** Layout change listener that moves the stack to the nearest valid position on rotation. */
|
||||||
private OnLayoutChangeListener mOrientationChangedListener;
|
private OnLayoutChangeListener mOrientationChangedListener;
|
||||||
/** Whether the stack was on the left side of the screen prior to rotation. */
|
|
||||||
private boolean mWasOnLeftBeforeRotation = false;
|
@Nullable private RelativeStackPosition mRelativeStackPositionBeforeRotation;
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
private int mMaxBubbles;
|
private int mMaxBubbles;
|
||||||
private int mBubbleSize;
|
private int mBubbleSize;
|
||||||
@@ -967,9 +962,10 @@ public class BubbleStackView extends FrameLayout
|
|||||||
mExpandedViewContainer.setTranslationY(getExpandedViewY());
|
mExpandedViewContainer.setTranslationY(getExpandedViewY());
|
||||||
mExpandedViewContainer.setAlpha(1f);
|
mExpandedViewContainer.setAlpha(1f);
|
||||||
}
|
}
|
||||||
if (mVerticalPosPercentBeforeRotation >= 0) {
|
if (mRelativeStackPositionBeforeRotation != null) {
|
||||||
mStackAnimationController.moveStackToSimilarPositionAfterRotation(
|
mStackAnimationController.setStackPosition(
|
||||||
mWasOnLeftBeforeRotation, mVerticalPosPercentBeforeRotation);
|
mRelativeStackPositionBeforeRotation);
|
||||||
|
mRelativeStackPositionBeforeRotation = null;
|
||||||
}
|
}
|
||||||
removeOnLayoutChangeListener(mOrientationChangedListener);
|
removeOnLayoutChangeListener(mOrientationChangedListener);
|
||||||
};
|
};
|
||||||
@@ -1231,13 +1227,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
com.android.internal.R.dimen.status_bar_height);
|
com.android.internal.R.dimen.status_bar_height);
|
||||||
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
|
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
|
||||||
|
|
||||||
final RectF allowablePos = mStackAnimationController.getAllowableStackPositionRegion();
|
mRelativeStackPositionBeforeRotation = mStackAnimationController.getRelativeStackPosition();
|
||||||
mWasOnLeftBeforeRotation = mStackAnimationController.isStackOnLeftSide();
|
|
||||||
mVerticalPosPercentBeforeRotation =
|
|
||||||
(mStackAnimationController.getStackPosition().y - allowablePos.top)
|
|
||||||
/ (allowablePos.bottom - allowablePos.top);
|
|
||||||
mVerticalPosPercentBeforeRotation =
|
|
||||||
Math.max(0f, Math.min(1f, mVerticalPosPercentBeforeRotation));
|
|
||||||
addOnLayoutChangeListener(mOrientationChangedListener);
|
addOnLayoutChangeListener(mOrientationChangedListener);
|
||||||
hideFlyoutImmediate();
|
hideFlyoutImmediate();
|
||||||
|
|
||||||
@@ -1506,7 +1496,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
if (getBubbleCount() == 0 && mShouldShowUserEducation) {
|
if (getBubbleCount() == 0 && mShouldShowUserEducation) {
|
||||||
// Override the default stack position if we're showing user education.
|
// Override the default stack position if we're showing user education.
|
||||||
mStackAnimationController.setStackPosition(
|
mStackAnimationController.setStackPosition(
|
||||||
mStackAnimationController.getDefaultStartPosition());
|
mStackAnimationController.getStartPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getBubbleCount() == 0) {
|
if (getBubbleCount() == 0) {
|
||||||
@@ -1721,7 +1711,7 @@ public class BubbleStackView extends FrameLayout
|
|||||||
// Post so we have height of mUserEducationView
|
// Post so we have height of mUserEducationView
|
||||||
mUserEducationView.post(() -> {
|
mUserEducationView.post(() -> {
|
||||||
final int viewHeight = mUserEducationView.getHeight();
|
final int viewHeight = mUserEducationView.getHeight();
|
||||||
PointF stackPosition = mStackAnimationController.getDefaultStartPosition();
|
PointF stackPosition = mStackAnimationController.getStartPosition();
|
||||||
final float translationY = stackPosition.y + (mBubbleSize / 2) - (viewHeight / 2);
|
final float translationY = stackPosition.y + (mBubbleSize / 2) - (viewHeight / 2);
|
||||||
mUserEducationView.setTranslationY(translationY);
|
mUserEducationView.setTranslationY(translationY);
|
||||||
mUserEducationView.animate()
|
mUserEducationView.animate()
|
||||||
@@ -2877,10 +2867,18 @@ public class BubbleStackView extends FrameLayout
|
|||||||
.floatValue();
|
.floatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStackStartPosition(RelativeStackPosition position) {
|
||||||
|
mStackAnimationController.setStackStartPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
public PointF getStackPosition() {
|
public PointF getStackPosition() {
|
||||||
return mStackAnimationController.getStackPosition();
|
return mStackAnimationController.getStackPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RelativeStackPosition getRelativeStackPosition() {
|
||||||
|
return mStackAnimationController.getRelativeStackPosition();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs the bubble UI event.
|
* Logs the bubble UI event.
|
||||||
*
|
*
|
||||||
@@ -2944,4 +2942,47 @@ public class BubbleStackView extends FrameLayout
|
|||||||
}
|
}
|
||||||
return bubbles;
|
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 androidx.dynamicanimation.animation.SpringForce;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.bubbles.BubbleStackView;
|
||||||
import com.android.systemui.util.FloatingContentCoordinator;
|
import com.android.systemui.util.FloatingContentCoordinator;
|
||||||
import com.android.systemui.util.animation.PhysicsAnimator;
|
import com.android.systemui.util.animation.PhysicsAnimator;
|
||||||
import com.android.systemui.util.magnetictarget.MagnetizedObject;
|
import com.android.systemui.util.magnetictarget.MagnetizedObject;
|
||||||
@@ -125,6 +126,9 @@ public class StackAnimationController extends
|
|||||||
*/
|
*/
|
||||||
private Rect mAnimatingToBounds = new Rect();
|
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. */
|
/** Whether or not the stack's start position has been set. */
|
||||||
private boolean mStackMovedToStartPosition = false;
|
private boolean mStackMovedToStartPosition = false;
|
||||||
|
|
||||||
@@ -431,21 +435,6 @@ public class StackAnimationController extends
|
|||||||
return stackPos;
|
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. */
|
/** Description of current animation controller state. */
|
||||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
pw.println("StackAnimationController state:");
|
pw.println("StackAnimationController state:");
|
||||||
@@ -815,7 +804,7 @@ public class StackAnimationController extends
|
|||||||
} else {
|
} else {
|
||||||
// When all children are removed ensure stack position is sane
|
// When all children are removed ensure stack position is sane
|
||||||
setStackPosition(mRestingStackPosition == null
|
setStackPosition(mRestingStackPosition == null
|
||||||
? getDefaultStartPosition()
|
? getStartPosition()
|
||||||
: mRestingStackPosition);
|
: mRestingStackPosition);
|
||||||
|
|
||||||
// Remove the stack from the coordinator since we don't have any bubbles and aren't
|
// 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.setVisibility(View.INVISIBLE);
|
||||||
mLayout.post(() -> {
|
mLayout.post(() -> {
|
||||||
setStackPosition(mRestingStackPosition == null
|
setStackPosition(mRestingStackPosition == null
|
||||||
? getDefaultStartPosition()
|
? getStartPosition()
|
||||||
: mRestingStackPosition);
|
: mRestingStackPosition);
|
||||||
mStackMovedToStartPosition = true;
|
mStackMovedToStartPosition = true;
|
||||||
mLayout.setVisibility(View.VISIBLE);
|
mLayout.setVisibility(View.VISIBLE);
|
||||||
@@ -938,15 +927,47 @@ public class StackAnimationController extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the default stack position, which is on the top left. */
|
public void setStackPosition(BubbleStackView.RelativeStackPosition position) {
|
||||||
public PointF getDefaultStartPosition() {
|
setStackPosition(position.getAbsolutePositionInRegion(getAllowableStackPositionRegion()));
|
||||||
boolean isRtl = mLayout != null
|
}
|
||||||
&& mLayout.getResources().getConfiguration().getLayoutDirection()
|
|
||||||
== View.LAYOUT_DIRECTION_RTL;
|
public BubbleStackView.RelativeStackPosition getRelativeStackPosition() {
|
||||||
return new PointF(isRtl
|
return new BubbleStackView.RelativeStackPosition(
|
||||||
? getAllowableStackPositionRegion().right
|
mStackPosition, getAllowableStackPositionRegion());
|
||||||
: getAllowableStackPositionRegion().left,
|
}
|
||||||
getAllowableStackPositionRegion().top + mStackStartingVerticalOffset);
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
private boolean isStackPositionSet() {
|
||||||
|
|||||||
Reference in New Issue
Block a user