Improve action bar transition
Improves the transition of the action bar between
the collapsed and expanded states.
Bug: 28935363
Change-Id: I89efe95aa045d04bab4208a001f82cb69b38fce5
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index aedc7df..28a6851 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -193,6 +193,13 @@
mGroupExpansionChanging = changing;
}
+ @Override
+ public void setActualHeightAnimating(boolean animating) {
+ if (mPrivateLayout != null) {
+ mPrivateLayout.setContentHeightAnimating(animating);
+ }
+ }
+
public NotificationContentView getPrivateLayout() {
return mPrivateLayout;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 2c302ed..b4f90c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -432,6 +432,8 @@
return false;
}
+ public void setActualHeightAnimating(boolean animating) {}
+
/**
* A listener notifying when {@link #getActualHeight} changes.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 21fed3c..a11263a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -106,13 +106,19 @@
private boolean mExpandable;
private boolean mClipToActualHeight = true;
private ExpandableNotificationRow mContainingNotification;
+ /** The visible type at the start of a touch driven transformation */
private int mTransformationStartVisibleType;
+ /** The visible type at the start of an animation driven transformation */
+ private int mAnimationStartVisibleType = UNDEFINED;
private boolean mUserExpanding;
private int mSingleLineWidthIndention;
private boolean mForceSelectNextLayout = true;
private PendingIntent mPreviousExpandedRemoteInputIntent;
private PendingIntent mPreviousHeadsUpRemoteInputIntent;
+ private int mContentHeightAtAnimationStart = UNDEFINED;
+
+
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
mHybridGroupManager = new HybridGroupManager(getContext(), this);
@@ -258,7 +264,14 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int previousHeight = 0;
+ if (mExpandedChild != null) {
+ previousHeight = mExpandedChild.getHeight();
+ }
super.onLayout(changed, left, top, right, bottom);
+ if (previousHeight != 0 && mExpandedChild.getHeight() != previousHeight) {
+ mContentHeightAtAnimationStart = previousHeight;
+ }
updateClipping();
invalidateOutline();
selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
@@ -408,24 +421,54 @@
* height, the notification is clipped instead of being further shrunk.
*/
private int getMinContentHeightHint() {
- if (mIsChildInGroup && (mVisibleType == VISIBLE_TYPE_SINGLELINE
- || mTransformationStartVisibleType == VISIBLE_TYPE_SINGLELINE)) {
+ if (mIsChildInGroup && isVisibleOrTransitioning(VISIBLE_TYPE_SINGLELINE)) {
return mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_action_list_height);
}
+
+ // Transition between heads-up & expanded, or pinned.
+ if (mHeadsUpChild != null && mExpandedChild != null) {
+ boolean transitioningBetweenHunAndExpanded =
+ isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
+ isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
+ boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED) && mIsHeadsUp;
+ if (transitioningBetweenHunAndExpanded || pinned) {
+ return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight());
+ }
+ }
+
+ // Size change of the expanded version
+ if ((mVisibleType == VISIBLE_TYPE_EXPANDED) && mContentHeightAtAnimationStart >= 0
+ && mExpandedChild != null) {
+ return Math.min(mContentHeightAtAnimationStart, mExpandedChild.getHeight());
+ }
+
int hint;
- if (mHeadsUpChild != null) {
+ if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
hint = mHeadsUpChild.getHeight();
+ } else if (mExpandedChild != null) {
+ hint = mExpandedChild.getHeight();
} else {
hint = mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_action_list_height);
}
- if (mExpandedChild != null) {
+
+ if (mExpandedChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_EXPANDED)) {
hint = Math.min(hint, mExpandedChild.getHeight());
}
return hint;
}
+ private boolean isTransitioningFromTo(int from, int to) {
+ return (mTransformationStartVisibleType == from || mAnimationStartVisibleType == from)
+ && mVisibleType == to;
+ }
+
+ private boolean isVisibleOrTransitioning(int type) {
+ return mVisibleType == type || mTransformationStartVisibleType == type
+ || mAnimationStartVisibleType == type;
+ }
+
private void updateContentTransformation() {
int visibleType = calculateVisibleType();
if (visibleType != mVisibleType) {
@@ -656,6 +699,7 @@
shownView.setVisible(true);
return;
}
+ mAnimationStartVisibleType = mVisibleType;
shownView.transformFrom(hiddenView);
getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
hiddenView.transformTo(shownView, new Runnable() {
@@ -664,6 +708,7 @@
if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
hiddenView.setVisible(false);
}
+ mAnimationStartVisibleType = UNDEFINED;
}
});
}
@@ -1082,4 +1127,10 @@
mHeadsUpRemoteInput.setRemoved();
}
}
+
+ public void setContentHeightAnimating(boolean animating) {
+ if (!animating) {
+ mContentHeightAtAnimationStart = UNDEFINED;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
index c0373be..8c72544 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -44,6 +44,16 @@
}
@Override
+ public void transformViewFullyFrom(TransformState otherState, float transformationAmount) {
+ // Don't do Y transform - let the wrapper handle this based on the content height
+ }
+
+ @Override
+ public void transformViewFullyTo(TransformState otherState, float transformationAmount) {
+ // Don't do Y transform - let the wrapper handle this based on the content height
+ }
+
+ @Override
protected void resetTransformedView() {
// We need to keep the Y transformation, because this is used to keep the action list
// aligned at the bottom, unrelated to transforms.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 0f94227..7ac0d80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -485,6 +485,7 @@
child.setTag(TAG_ANIMATOR_HEIGHT, null);
child.setTag(TAG_START_HEIGHT, null);
child.setTag(TAG_END_HEIGHT, null);
+ child.setActualHeightAnimating(false);
if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
((ExpandableNotificationRow) child).setGroupExpansionChanging(
false /* isExpansionChanging */);
@@ -505,6 +506,7 @@
child.setTag(TAG_ANIMATOR_HEIGHT, animator);
child.setTag(TAG_START_HEIGHT, child.getActualHeight());
child.setTag(TAG_END_HEIGHT, newEndValue);
+ child.setActualHeightAnimating(true);
}
private void startInsetAnimation(final ExpandableView child,