Adapted the animation to the full shade

The background and the shelf now animate properly on
the lockscreen when going to the full shade.

Test: Go to lockscreen from keyguard
Bug: 32437839
Change-Id: Idd7e8325cc91464ed9c943c5ae311576d8aaaebc
This commit is contained in:
Selim Cinek
2016-10-28 15:04:05 -07:00
parent aa417dac58
commit eccb5de73c
7 changed files with 106 additions and 3 deletions

View File

@@ -47,6 +47,8 @@ public abstract class ExpandableView extends FrameLayout {
private boolean mClipToActualHeight = true;
private boolean mChangingPosition = false;
private ViewGroup mTransientContainer;
private boolean mInShelf;
private boolean mTransformingInShelf;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -475,6 +477,29 @@ public abstract class ExpandableView extends FrameLayout {
return false;
}
/**
* @param inShelf whether the view is currently fully in the notification shelf.
*/
public void setInShelf(boolean inShelf) {
mInShelf = inShelf;
}
public boolean isInShelf() {
return mInShelf;
}
/**
* @param transformingInShelf whether the view is currently transforming into the shelf in an
* animated way
*/
public void setTransformingInShelf(boolean transformingInShelf) {
mTransformingInShelf = transformingInShelf;
}
public boolean isTransformingIntoShelf() {
return mTransformingInShelf;
}
/**
* A listener notifying when {@link #getActualHeight} changes.
*/

View File

@@ -60,6 +60,8 @@ public class NotificationShelf extends ActivatableNotificationView {
private NotificationStackScrollLayout mHostLayout;
private int mMaxLayoutHeight;
private int mPaddingBetweenElements;
private int mNotGoneIndex;
private boolean mHasItemsInStableShelf;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -154,9 +156,14 @@ public class NotificationShelf extends ActivatableNotificationView {
mShelfState.shadowAlpha = 1.0f;
mShelfState.isBottomClipped = false;
mShelfState.hideSensitive = false;
if (mNotGoneIndex != -1) {
mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex);
}
mShelfState.hasItemsInStableShelf = lastViewState.inShelf;
} else {
mShelfState.hidden = true;
mShelfState.location = ExpandableViewState.LOCATION_GONE;
mShelfState.hasItemsInStableShelf = false;
}
}
@@ -169,6 +176,7 @@ public class NotificationShelf extends ActivatableNotificationView {
mNotificationIconContainer.resetViewStates();
float numIconsInShelf = 0.0f;
int shelfIndex = mAmbientState.getShelfIndex();
mNotGoneIndex = -1;
// find the first view that doesn't overlap with the shelf
for (int i = shelfIndex - 1; i >= 0; i--) {
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
@@ -198,6 +206,9 @@ public class NotificationShelf extends ActivatableNotificationView {
updateNotificationClipHeight(row, notificationClipEnd);
updateIconAppearance(shelfStart, row, iconState, icon);
numIconsInShelf += iconState.iconAppearAmount;
if (row.getTranslationY() >= getTranslationY()) {
mNotGoneIndex = i;
}
}
for (int i = mHostLayout.getChildCount() - 1; i >= shelfIndex; i--) {
// We need to reset the clipping in case a notification switches from high to low
@@ -301,6 +312,13 @@ public class NotificationShelf extends ActivatableNotificationView {
iconState.hidden = transitionAmount == 0.0f;
row.setIconTransformationAmount(transitionAmount);
icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
iconState.iconAppearAmount = 1.0f;
iconState.alpha = 1.0f;
iconState.scaleX = shelfIconSize / icon.getHeight();
iconState.scaleY = iconState.scaleX;
iconState.hidden = false;
}
}
private float getFullyClosedTranslation() {
@@ -335,6 +353,10 @@ public class NotificationShelf extends ActivatableNotificationView {
updateOutline();
}
public boolean hidesBackground() {
return mHideBackground;
}
@Override
protected boolean needsOutline() {
return !mHideBackground && super.needsOutline();
@@ -353,14 +375,35 @@ public class NotificationShelf extends ActivatableNotificationView {
mMaxLayoutHeight = maxLayoutHeight;
}
/**
* @return the index of the notification at which the shelf visually resides
*/
public int getNotGoneIndex() {
return mNotGoneIndex;
}
private void setHasItemsInStableShelf(boolean hasItemsInStableShelf) {
mHasItemsInStableShelf = hasItemsInStableShelf;
}
/**
* @return whether the shelf has any icons in it when a potential animation has finished, i.e
* if the current state would be applied right now
*/
public boolean hasItemsInStableShelf() {
return mHasItemsInStableShelf;
}
private class ShelfState extends ExpandableViewState {
private float iconContainerTranslation;
private boolean hasItemsInStableShelf;
@Override
public void applyToView(View view) {
super.applyToView(view);
updateAppearance();
setIconContainerTranslation(iconContainerTranslation);
setHasItemsInStableShelf(hasItemsInStableShelf);
}
@Override
@@ -368,6 +411,7 @@ public class NotificationShelf extends ActivatableNotificationView {
super.animateTo(child, properties);
updateAppearance();
setIconContainerTranslation(iconContainerTranslation);
setHasItemsInStableShelf(hasItemsInStableShelf);
}
}
}

View File

@@ -86,6 +86,7 @@ public class ExpandableViewState extends ViewState {
public boolean hideSensitive;
public boolean belowShelf;
public float shadowAlpha;
public boolean inShelf;
/**
* How much the child overlaps with the previous child on top. This is used to
@@ -171,6 +172,9 @@ public class ExpandableViewState extends ViewState {
if (oldClipTopAmount != this.clipTopAmount) {
expandableView.setClipTopAmount(this.clipTopAmount);
}
expandableView.setTransformingInShelf(false);
expandableView.setInShelf(inShelf);
}
}
@@ -220,6 +224,11 @@ public class ExpandableViewState extends ViewState {
if (properties.wasAdded(child)) {
expandableView.performAddAnimation(properties.delay, properties.duration);
}
if (!expandableView.isInShelf() && this.inShelf) {
expandableView.setTransformingInShelf(true);
}
expandableView.setInShelf(this.inShelf);
}
private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) {

View File

@@ -2127,10 +2127,17 @@ public class NotificationStackScrollLayout extends ViewGroup
top = (int) firstView.getTranslationY();
}
}
ActivatableNotificationView lastView = mLastVisibleBackgroundChild;
ActivatableNotificationView lastView = mShelf.hasItemsInStableShelf()
? mShelf
: mLastVisibleBackgroundChild;
int bottom = 0;
if (lastView != null) {
int finalTranslationY = (int) ViewState.getFinalTranslationY(lastView);
int finalTranslationY;
if (lastView == mShelf) {
finalTranslationY = (int) mShelf.getTranslationY();
} else {
finalTranslationY = (int) ViewState.getFinalTranslationY(lastView);
}
int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
int finalBottom = finalTranslationY + finalHeight;
finalBottom = Math.min(finalBottom, getHeight());
@@ -3979,6 +3986,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
addView(mShelf, index);
mAmbientState.setShelf(shelf);
mStateAnimator.setShelf(shelf);
shelf.bind(mAmbientState, this);
}

View File

@@ -501,6 +501,7 @@ public class StackScrollAlgorithm {
childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
if (childViewState.yTranslation >= shelfStart) {
childViewState.hidden = true;
childViewState.inShelf = true;
}
if (!ambientState.isShadeExpanded()) {
childViewState.height = (int) (mStatusBarHeight - childViewState.yTranslation);

View File

@@ -83,6 +83,7 @@ public class StackScrollState {
viewState.hidden = false;
viewState.scaleX = view.getScaleX();
viewState.scaleY = view.getScaleY();
viewState.inShelf = false;
}
public ExpandableViewState getViewStateForView(View requestedView) {

View File

@@ -28,6 +28,7 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationShelf;
import java.util.ArrayList;
import java.util.HashSet;
@@ -75,6 +76,7 @@ public class StackStateAnimator {
private int mHeadsUpAppearHeightBottom;
private boolean mShadeExpanded;
private ArrayList<View> mChildrenToClearFromOverlay = new ArrayList<>();
private NotificationShelf mShelf;
public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
mHostLayout = hostLayout;
@@ -287,9 +289,18 @@ public class StackStateAnimator {
}
private long calculateDelayGoToFullShade(ExpandableViewState viewState) {
int shelfIndex = mShelf.getNotGoneIndex();
float index = viewState.notGoneIndex;
long result = 0;
if (index > shelfIndex) {
float diff = index - shelfIndex;
diff = (float) Math.pow(diff, 0.7f);
result += (long) (diff * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE * 0.25);
index = shelfIndex;
}
index = (float) Math.pow(index, 0.7f);
return (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE);
result += (long) (index * ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE);
return result;
}
/**
@@ -501,4 +512,8 @@ public class StackStateAnimator {
public void setShadeExpanded(boolean shadeExpanded) {
mShadeExpanded = shadeExpanded;
}
public void setShelf(NotificationShelf shelf) {
mShelf = shelf;
}
}