OSDN Git Service

Improve action bar transition
authorAdrian Roos <roosa@google.com>
Mon, 13 Jun 2016 21:54:39 +0000 (14:54 -0700)
committerAdrian Roos <roosa@google.com>
Tue, 14 Jun 2016 03:53:45 +0000 (03:53 +0000)
Improves the transition of the action bar between
the collapsed and expanded states.

Bug: 28935363
Change-Id: I89efe95aa045d04bab4208a001f82cb69b38fce5

packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java

index aedc7df..28a6851 100644 (file)
@@ -193,6 +193,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
         mGroupExpansionChanging = changing;
     }
 
+    @Override
+    public void setActualHeightAnimating(boolean animating) {
+        if (mPrivateLayout != null) {
+            mPrivateLayout.setContentHeightAnimating(animating);
+        }
+    }
+
     public NotificationContentView getPrivateLayout() {
         return mPrivateLayout;
     }
index 2c302ed..b4f90c6 100644 (file)
@@ -432,6 +432,8 @@ public abstract class ExpandableView extends FrameLayout {
         return false;
     }
 
+    public void setActualHeightAnimating(boolean animating) {}
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
index 21fed3c..a11263a 100644 (file)
@@ -106,13 +106,19 @@ public class NotificationContentView extends FrameLayout {
     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 @@ public class NotificationContentView extends FrameLayout {
 
     @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 @@ public class NotificationContentView extends FrameLayout {
      *         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 @@ public class NotificationContentView extends FrameLayout {
             shownView.setVisible(true);
             return;
         }
+        mAnimationStartVisibleType = mVisibleType;
         shownView.transformFrom(hiddenView);
         getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
         hiddenView.transformTo(shownView, new Runnable() {
@@ -664,6 +708,7 @@ public class NotificationContentView extends FrameLayout {
                 if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
                     hiddenView.setVisible(false);
                 }
+                mAnimationStartVisibleType = UNDEFINED;
             }
         });
     }
@@ -1082,4 +1127,10 @@ public class NotificationContentView extends FrameLayout {
             mHeadsUpRemoteInput.setRemoved();
         }
     }
+
+    public void setContentHeightAnimating(boolean animating) {
+        if (!animating) {
+            mContentHeightAtAnimationStart = UNDEFINED;
+        }
+    }
 }
index c0373be..8c72544 100644 (file)
@@ -44,6 +44,16 @@ public class ActionListTransformState extends TransformState {
     }
 
     @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.
index 0f94227..7ac0d80 100644 (file)
@@ -485,6 +485,7 @@ public class StackStateAnimator {
                 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 @@ public class StackStateAnimator {
         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,