Added possibility to use canned animation for icons
Icons now move in a canned animation from the shelf position to the icon. Test: adb shell setprop debug.icon_opening_animations true && adb shell killall com.android.systemui Bug: 32437839 Change-Id: I82b6de37ac7a179aeb5d16bd663d566c2f338b1a
This commit is contained in:
@@ -193,7 +193,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
private View mChildAfterViewWhenDismissed;
|
||||
private View mGroupParentWhenDismissed;
|
||||
private boolean mRefocusOnDismiss;
|
||||
private float mIconTransformationAmount;
|
||||
private float mContentTransformationAmount;
|
||||
private boolean mIconsVisible = true;
|
||||
private boolean mAboveShelf;
|
||||
private boolean mIsLastChild;
|
||||
@@ -837,23 +837,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
/**
|
||||
* Set how much this notification is transformed into an icon.
|
||||
*
|
||||
* @param iconTransformationAmount A value from 0 to 1 indicating how much we are transformed
|
||||
* to an icon
|
||||
* @param contentTransformationAmount A value from 0 to 1 indicating how much we are transformed
|
||||
* to the content away
|
||||
* @param isLastChild is this the last child in the list. If true, then the transformation is
|
||||
* different since it's content fades out.
|
||||
*/
|
||||
public void setIconTransformationAmount(float iconTransformationAmount, boolean isLastChild) {
|
||||
public void setContentTransformationAmount(float contentTransformationAmount,
|
||||
boolean isLastChild) {
|
||||
boolean changeTransformation = isLastChild != mIsLastChild;
|
||||
changeTransformation |= mIconTransformationAmount != iconTransformationAmount;
|
||||
changeTransformation |= mContentTransformationAmount != contentTransformationAmount;
|
||||
mIsLastChild = isLastChild;
|
||||
mIconTransformationAmount = iconTransformationAmount;
|
||||
mContentTransformationAmount = contentTransformationAmount;
|
||||
if (changeTransformation) {
|
||||
updateContentTransformation();
|
||||
boolean iconsVisible = mIconTransformationAmount == 0.0f;
|
||||
if (iconsVisible != mIconsVisible) {
|
||||
mIconsVisible = iconsVisible;
|
||||
updateIconVisibilities();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the icons to be visible of this notification.
|
||||
*/
|
||||
public void setIconsVisible(boolean iconsVisible) {
|
||||
if (iconsVisible != mIconsVisible) {
|
||||
mIconsVisible = iconsVisible;
|
||||
updateIconVisibilities();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,9 +870,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
|
||||
private void updateContentTransformation() {
|
||||
float contentAlpha;
|
||||
float translationY = - mIconTransformationAmount * mIconTransformContentShift;
|
||||
float translationY = -mContentTransformationAmount * mIconTransformContentShift;
|
||||
if (mIsLastChild) {
|
||||
contentAlpha = 1.0f - mIconTransformationAmount;
|
||||
contentAlpha = 1.0f - mContentTransformationAmount;
|
||||
contentAlpha = Math.min(contentAlpha / 0.5f, 1.0f);
|
||||
contentAlpha = Interpolators.ALPHA_OUT.getInterpolation(contentAlpha);
|
||||
translationY *= 0.4f;
|
||||
@@ -1871,8 +1877,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onYTranslationAnimationFinished() {
|
||||
super.onYTranslationAnimationFinished();
|
||||
protected void onYTranslationAnimationFinished(View view) {
|
||||
super.onYTranslationAnimationFinished(view);
|
||||
if (mHeadsupDisappearRunning) {
|
||||
setHeadsUpAnimatingAway(false);
|
||||
}
|
||||
|
||||
@@ -208,6 +208,12 @@ public class NotificationData {
|
||||
expandedIcon = null;
|
||||
throw new IconException("Couldn't create icon: " + ic);
|
||||
}
|
||||
expandedIcon.setOnVisibilityChangedListener(
|
||||
newVisibility -> {
|
||||
if (row != null) {
|
||||
row.setIconsVisible(newVisibility != View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setIconTag(int key, Object tag) {
|
||||
|
||||
@@ -18,7 +18,10 @@ package com.android.systemui.statusbar;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@@ -34,7 +37,6 @@ import com.android.systemui.statusbar.stack.ExpandableViewState;
|
||||
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.stack.StackScrollState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
@@ -43,10 +45,11 @@ import java.util.WeakHashMap;
|
||||
*/
|
||||
public class NotificationShelf extends ActivatableNotificationView {
|
||||
|
||||
private static final boolean USE_ANIMATIONS_WHEN_OPENING =
|
||||
SystemProperties.getBoolean("debug.icon_opening_animations", true);
|
||||
private ViewInvertHelper mViewInvertHelper;
|
||||
private boolean mDark;
|
||||
private NotificationIconContainer mShelfIcons;
|
||||
private ArrayList<StatusBarIconView> mIcons = new ArrayList<>();
|
||||
private ShelfState mShelfState;
|
||||
private int[] mTmp = new int[2];
|
||||
private boolean mHideBackground;
|
||||
@@ -204,8 +207,6 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
continue;
|
||||
}
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
|
||||
StatusBarIconView icon = row.getEntry().expandedIcon;
|
||||
NotificationIconContainer.IconState iconState = iconStates.get(icon);
|
||||
float notificationClipEnd;
|
||||
float shelfStart = getTranslationY();
|
||||
boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight();
|
||||
@@ -223,8 +224,7 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
}
|
||||
updateNotificationClipHeight(row, notificationClipEnd);
|
||||
float inShelfAmount = updateIconAppearance(row, iconState, icon, expandAmount,
|
||||
isLastChild);
|
||||
float inShelfAmount = updateIconAppearance(row, expandAmount, isLastChild);
|
||||
numViewsInShelf += inShelfAmount;
|
||||
int ownColorUntinted = row.getBackgroundColorWithoutTint();
|
||||
if (row.getTranslationY() >= getTranslationY() && mNotGoneIndex == -1) {
|
||||
@@ -250,7 +250,7 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
}
|
||||
mShelfIcons.calculateIconTranslations();
|
||||
mShelfIcons.applyIconStates();
|
||||
setVisibility(numViewsInShelf != 0.0f && mAmbientState.isShadeExpanded()
|
||||
setVisibility(mAmbientState.isShadeExpanded()
|
||||
? VISIBLE
|
||||
: INVISIBLE);
|
||||
boolean hideBackground = numViewsInShelf < 1.0f;
|
||||
@@ -275,41 +275,103 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
/**
|
||||
* @return the icon amount how much this notification is in the shelf;
|
||||
*/
|
||||
private float updateIconAppearance(ExpandableNotificationRow row,
|
||||
NotificationIconContainer.IconState iconState, StatusBarIconView icon,
|
||||
float expandAmount, boolean isLastChild) {
|
||||
private float updateIconAppearance(ExpandableNotificationRow row, float expandAmount,
|
||||
boolean isLastChild) {
|
||||
// Let calculate how much the view is in the shelf
|
||||
float viewStart = row.getTranslationY();
|
||||
int transformHeight = row.getActualHeight() + mPaddingBetweenElements;
|
||||
int fullHeight = row.getActualHeight() + mPaddingBetweenElements;
|
||||
float iconTransformDistance = getIntrinsicHeight() * 1.5f;
|
||||
if (isLastChild) {
|
||||
transformHeight =
|
||||
Math.min(transformHeight, row.getMinHeight() - getIntrinsicHeight());
|
||||
fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight());
|
||||
iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight()
|
||||
- getIntrinsicHeight());
|
||||
}
|
||||
float viewEnd = viewStart + transformHeight;
|
||||
float iconAppearAmount;
|
||||
float yTranslation;
|
||||
float alpha = 1.0f;
|
||||
float viewEnd = viewStart + fullHeight;
|
||||
float fullTransitionAmount;
|
||||
float iconTransitonAmount;
|
||||
if (viewEnd >= getTranslationY() && (mAmbientState.isShadeExpanded()
|
||||
|| (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
|
||||
if (viewStart < getTranslationY()) {
|
||||
float linearAmount = (getTranslationY() - viewStart) / transformHeight;
|
||||
|
||||
float fullAmount = (getTranslationY() - viewStart) / fullHeight;
|
||||
float interpolatedAmount = Interpolators.ACCELERATE_DECELERATE.getInterpolation(
|
||||
linearAmount);
|
||||
fullAmount);
|
||||
interpolatedAmount = NotificationUtils.interpolate(
|
||||
interpolatedAmount, linearAmount, expandAmount);
|
||||
iconAppearAmount = 1.0f - interpolatedAmount;
|
||||
interpolatedAmount, fullAmount, expandAmount);
|
||||
fullTransitionAmount = 1.0f - interpolatedAmount;
|
||||
|
||||
iconTransitonAmount = (getTranslationY() - viewStart) / iconTransformDistance;
|
||||
iconTransitonAmount = Math.min(1.0f, iconTransitonAmount);
|
||||
iconTransitonAmount = 1.0f - iconTransitonAmount;
|
||||
|
||||
} else {
|
||||
iconAppearAmount = 1.0f;
|
||||
fullTransitionAmount = 1.0f;
|
||||
iconTransitonAmount = 1.0f;
|
||||
}
|
||||
} else {
|
||||
iconAppearAmount = 0.0f;
|
||||
fullTransitionAmount = 0.0f;
|
||||
iconTransitonAmount = 0.0f;
|
||||
}
|
||||
row.setContentTransformationAmount(iconTransitonAmount, isLastChild);
|
||||
updateIconPositioning(row, iconTransitonAmount, fullTransitionAmount);
|
||||
return fullTransitionAmount;
|
||||
}
|
||||
|
||||
private void updateIconPositioning(ExpandableNotificationRow row, float iconTransitionAmount,
|
||||
float fullTransitionAmount) {
|
||||
StatusBarIconView icon = row.getEntry().expandedIcon;
|
||||
NotificationIconContainer.IconState iconState = getIconState(icon);
|
||||
if (iconState == null) {
|
||||
return;
|
||||
}
|
||||
float clampedAmount = iconTransitionAmount > 0.5f ? 1.0f : 0.0f;
|
||||
boolean isLastChild = isLastChild(row);
|
||||
if (clampedAmount == iconTransitionAmount) {
|
||||
iconState.keepClampedPosition = false;
|
||||
}
|
||||
if (clampedAmount == fullTransitionAmount) {
|
||||
iconState.useFullTransitionAmount = fullTransitionAmount == 0.0f;
|
||||
}
|
||||
float transitionAmount;
|
||||
boolean needCannedAnimation = iconState.clampedAppearAmount == 1.0f
|
||||
&& clampedAmount == 0.0f;
|
||||
if (isLastChild || !USE_ANIMATIONS_WHEN_OPENING || iconState.useFullTransitionAmount) {
|
||||
transitionAmount = iconTransitionAmount;
|
||||
} else if (iconState.keepClampedPosition
|
||||
&& iconState.clampedAppearAmount != clampedAmount) {
|
||||
// We animated to the clamped amount but then decided to go the other way. Let's
|
||||
// animate it to the new position
|
||||
transitionAmount = iconTransitionAmount;
|
||||
iconState.needsCannedAnimation = true;
|
||||
iconState.keepClampedPosition = false;
|
||||
} else if (needCannedAnimation || iconState.keepClampedPosition
|
||||
|| iconState.iconAppearAmount == 1.0f) {
|
||||
// We need to perform a canned animation since we crossed the treshhold
|
||||
transitionAmount = clampedAmount;
|
||||
iconState.keepClampedPosition = iconState.keepClampedPosition || needCannedAnimation;
|
||||
iconState.needsCannedAnimation = needCannedAnimation;
|
||||
} else {
|
||||
transitionAmount = iconTransitionAmount;
|
||||
}
|
||||
iconState.iconAppearAmount = !USE_ANIMATIONS_WHEN_OPENING
|
||||
|| iconState.useFullTransitionAmount
|
||||
? fullTransitionAmount
|
||||
: transitionAmount;
|
||||
iconState.clampedAppearAmount = clampedAmount;
|
||||
setIconTransformationAmount(row, transitionAmount);
|
||||
}
|
||||
|
||||
private boolean isLastChild(ExpandableNotificationRow row) {
|
||||
return row == mAmbientState.getLastVisibleBackgroundChild();
|
||||
}
|
||||
|
||||
private void setIconTransformationAmount(ExpandableNotificationRow row,
|
||||
float transitionAmount) {
|
||||
StatusBarIconView icon = row.getEntry().expandedIcon;
|
||||
NotificationIconContainer.IconState iconState = getIconState(icon);
|
||||
|
||||
// Lets now calculate how much of the transformation has already happened. This is different
|
||||
// from the above, since we only start transforming when the view is already quite a bit
|
||||
// pushed in.
|
||||
View rowIcon = row.getNotificationIcon();
|
||||
float notificationIconPosition = viewStart;
|
||||
float notificationIconPosition = row.getTranslationY();
|
||||
float notificationIconSize = 0.0f;
|
||||
int iconTopPadding;
|
||||
if (rowIcon != null) {
|
||||
@@ -322,28 +384,18 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
float shelfIconPosition = getTranslationY() + icon.getTop();
|
||||
shelfIconPosition += ((1.0f - icon.getIconScale()) * icon.getHeight()) / 2.0f;
|
||||
float transitionDistance = getIntrinsicHeight() * 1.5f;
|
||||
if (isLastChild) {
|
||||
if (row == mAmbientState.getLastVisibleBackgroundChild()) {
|
||||
transitionDistance = Math.min(transitionDistance, row.getMinHeight()
|
||||
- getIntrinsicHeight());
|
||||
}
|
||||
float transformationStartPosition = getTranslationY() - transitionDistance;
|
||||
float transitionAmount = 0.0f;
|
||||
if (viewStart < transformationStartPosition
|
||||
|| (!mAmbientState.isShadeExpanded()
|
||||
&& (row.isPinned() || row.isHeadsUpAnimatingAway()))) {
|
||||
// We simply place it on the icon of the notification
|
||||
yTranslation = notificationIconPosition - shelfIconPosition;
|
||||
} else {
|
||||
transitionAmount = (viewStart - transformationStartPosition)
|
||||
/ transitionDistance;
|
||||
float startPosition = transformationStartPosition + iconTopPadding;
|
||||
yTranslation = NotificationUtils.interpolate(
|
||||
startPosition - shelfIconPosition, 0, transitionAmount);
|
||||
// If we are merging into the shelf, lets make sure the shelf is at least on our height,
|
||||
// otherwise the icons won't be visible.
|
||||
setTranslationZ(Math.max(getTranslationZ(), row.getTranslationZ()));
|
||||
}
|
||||
float iconYTranslation = NotificationUtils.interpolate(
|
||||
Math.min(notificationIconPosition, transformationStartPosition + iconTopPadding)
|
||||
- shelfIconPosition,
|
||||
0,
|
||||
transitionAmount);
|
||||
float shelfIconSize = icon.getHeight() * icon.getIconScale();
|
||||
float alpha = 1.0f;
|
||||
if (!row.isShowingIcon()) {
|
||||
// The view currently doesn't have an icon, lets transform it in!
|
||||
alpha = transitionAmount;
|
||||
@@ -352,15 +404,12 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
// The notification size is different from the size in the shelf / statusbar
|
||||
float newSize = NotificationUtils.interpolate(notificationIconSize, shelfIconSize,
|
||||
transitionAmount);
|
||||
row.setIconTransformationAmount(transitionAmount, isLastChild);
|
||||
if (iconState != null) {
|
||||
iconState.scaleX = newSize / icon.getHeight() / icon.getIconScale();
|
||||
iconState.scaleY = iconState.scaleX;
|
||||
iconState.hidden = transitionAmount == 0.0f;
|
||||
iconState.iconAppearAmount = iconAppearAmount;
|
||||
iconState.alpha = alpha;
|
||||
iconState.yTranslation = yTranslation;
|
||||
icon.setVisibility(transitionAmount == 0.0f ? INVISIBLE : VISIBLE);
|
||||
iconState.yTranslation = iconYTranslation;
|
||||
if (row.isInShelf() && !row.isTransformingIntoShelf()) {
|
||||
iconState.iconAppearAmount = 1.0f;
|
||||
iconState.alpha = 1.0f;
|
||||
@@ -369,7 +418,10 @@ public class NotificationShelf extends ActivatableNotificationView {
|
||||
iconState.hidden = false;
|
||||
}
|
||||
}
|
||||
return iconAppearAmount;
|
||||
}
|
||||
|
||||
private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
|
||||
return mShelfIcons.getIconState(icon);
|
||||
}
|
||||
|
||||
private float getFullyClosedTranslation() {
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.util.FloatProperty;
|
||||
import android.util.Log;
|
||||
import android.util.Property;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -102,6 +103,7 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
private ObjectAnimator mIconAppearAnimator;
|
||||
private ObjectAnimator mDotAnimator;
|
||||
private float mDotAppearAmount;
|
||||
private OnVisibilityChangedListener mOnVisibilityChangedListener;
|
||||
|
||||
public StatusBarIconView(Context context, String slot, Notification notification) {
|
||||
this(context, slot, notification, false);
|
||||
@@ -525,7 +527,23 @@ public class StatusBarIconView extends AnimatedImageView {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
super.setVisibility(visibility);
|
||||
if (mOnVisibilityChangedListener != null) {
|
||||
mOnVisibilityChangedListener.onVisibilityChanged(visibility);
|
||||
}
|
||||
}
|
||||
|
||||
public float getDotAppearAmount() {
|
||||
return mDotAppearAmount;
|
||||
}
|
||||
|
||||
public void setOnVisibilityChangedListener(OnVisibilityChangedListener listener) {
|
||||
mOnVisibilityChangedListener = listener;
|
||||
}
|
||||
|
||||
public interface OnVisibilityChangedListener {
|
||||
void onVisibilityChanged(int newVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.WeakHashMap;
|
||||
public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
private static final String TAG = "NotificationIconContainer";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final int CANNED_ANIMATION_DURATION = 100;
|
||||
private static final AnimationProperties DOT_ANIMATION_PROPERTIES = new AnimationProperties() {
|
||||
private AnimationFilter mAnimationFilter = new AnimationFilter().animateX();
|
||||
|
||||
@@ -49,6 +50,26 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
}
|
||||
}.setDuration(200);
|
||||
|
||||
private static final AnimationProperties ICON_ANIMATION_PROPERTIES = new AnimationProperties() {
|
||||
private AnimationFilter mAnimationFilter = new AnimationFilter().animateY().animateAlpha();
|
||||
// TODO: add scale
|
||||
|
||||
@Override
|
||||
public AnimationFilter getAnimationFilter() {
|
||||
return mAnimationFilter;
|
||||
}
|
||||
}.setDuration(CANNED_ANIMATION_DURATION);
|
||||
|
||||
private static final AnimationProperties mTempProperties = new AnimationProperties() {
|
||||
private AnimationFilter mAnimationFilter = new AnimationFilter();
|
||||
// TODO: add scale
|
||||
|
||||
@Override
|
||||
public AnimationFilter getAnimationFilter() {
|
||||
return mAnimationFilter;
|
||||
}
|
||||
}.setDuration(CANNED_ANIMATION_DURATION);
|
||||
|
||||
private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
|
||||
private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
|
||||
|
||||
@@ -66,7 +87,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
private float mActualPaddingEnd = -1;
|
||||
private float mActualPaddingStart = -1;
|
||||
private boolean mChangingViewPositions;
|
||||
private int mAnimationStartIndex = -1;
|
||||
private int mAddAnimationStartIndex = -1;
|
||||
private int mCannedAnimationStartIndex = -1;
|
||||
|
||||
public NotificationIconContainer(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -121,7 +143,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
childState.applyToView(child);
|
||||
}
|
||||
}
|
||||
mAnimationStartIndex = -1;
|
||||
mAddAnimationStartIndex = -1;
|
||||
mCannedAnimationStartIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,10 +156,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
int childIndex = indexOfChild(child);
|
||||
if (childIndex < getChildCount() - 1
|
||||
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
|
||||
if (mAnimationStartIndex < 0) {
|
||||
mAnimationStartIndex = childIndex;
|
||||
if (mAddAnimationStartIndex < 0) {
|
||||
mAddAnimationStartIndex = childIndex;
|
||||
} else {
|
||||
mAnimationStartIndex = Math.min(mAnimationStartIndex, childIndex);
|
||||
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, childIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,10 +172,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
|
||||
&& child.getVisibility() == VISIBLE) {
|
||||
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
|
||||
if (mAnimationStartIndex < 0) {
|
||||
mAnimationStartIndex = animationStartIndex;
|
||||
if (mAddAnimationStartIndex < 0) {
|
||||
mAddAnimationStartIndex = animationStartIndex;
|
||||
} else {
|
||||
mAnimationStartIndex = Math.min(mAnimationStartIndex, animationStartIndex);
|
||||
mAddAnimationStartIndex = Math.min(mAddAnimationStartIndex, animationStartIndex);
|
||||
}
|
||||
}
|
||||
if (!mChangingViewPositions) {
|
||||
@@ -305,28 +328,64 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
mChangingViewPositions = changingViewPositions;
|
||||
}
|
||||
|
||||
public IconState getIconState(StatusBarIconView icon) {
|
||||
return mIconStates.get(icon);
|
||||
}
|
||||
|
||||
public class IconState extends ViewState {
|
||||
public float iconAppearAmount = 1.0f;
|
||||
public float clampedAppearAmount = 1.0f;
|
||||
public int visibleState;
|
||||
public boolean justAdded = true;
|
||||
public boolean needsCannedAnimation;
|
||||
public boolean keepClampedPosition;
|
||||
public boolean useFullTransitionAmount;
|
||||
|
||||
@Override
|
||||
public void applyToView(View view) {
|
||||
if (view instanceof StatusBarIconView) {
|
||||
StatusBarIconView icon = (StatusBarIconView) view;
|
||||
AnimationProperties animationProperties = DOT_ANIMATION_PROPERTIES;
|
||||
boolean animate = false;
|
||||
AnimationProperties animationProperties = null;
|
||||
if (justAdded) {
|
||||
super.applyToView(icon);
|
||||
icon.setAlpha(0.0f);
|
||||
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
|
||||
animationProperties = ADD_ICON_PROPERTIES;
|
||||
animate = true;
|
||||
} else if (visibleState != icon.getVisibleState()) {
|
||||
animationProperties = DOT_ANIMATION_PROPERTIES;
|
||||
animate = true;
|
||||
}
|
||||
boolean animate = visibleState != icon.getVisibleState() || justAdded;
|
||||
if (!animate && mAnimationStartIndex >= 0
|
||||
if (!animate && mAddAnimationStartIndex >= 0
|
||||
&& indexOfChild(view) >= mAddAnimationStartIndex
|
||||
&& (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
|
||||
|| visibleState != StatusBarIconView.STATE_HIDDEN)) {
|
||||
int viewIndex = indexOfChild(view);
|
||||
animate = viewIndex >= mAnimationStartIndex;
|
||||
animationProperties = DOT_ANIMATION_PROPERTIES;
|
||||
animate = true;
|
||||
}
|
||||
if (needsCannedAnimation) {
|
||||
AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
|
||||
animationFilter.reset();
|
||||
animationFilter.combineFilter(ICON_ANIMATION_PROPERTIES.getAnimationFilter());
|
||||
if (animationProperties != null) {
|
||||
animationFilter.combineFilter(animationProperties.getAnimationFilter());
|
||||
}
|
||||
animationProperties = mTempProperties;
|
||||
animationProperties.setDuration(CANNED_ANIMATION_DURATION);
|
||||
animate = true;
|
||||
mCannedAnimationStartIndex = indexOfChild(view);
|
||||
}
|
||||
if (!animate && mCannedAnimationStartIndex >= 0
|
||||
&& indexOfChild(view) > mCannedAnimationStartIndex
|
||||
&& (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
|
||||
|| visibleState != StatusBarIconView.STATE_HIDDEN)) {
|
||||
AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
|
||||
animationFilter.reset();
|
||||
animationFilter.animateX();
|
||||
animationProperties = mTempProperties;
|
||||
animationProperties.setDuration(CANNED_ANIMATION_DURATION);
|
||||
animate = true;
|
||||
}
|
||||
icon.setVisibleState(visibleState);
|
||||
if (animate) {
|
||||
@@ -336,6 +395,13 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
|
||||
}
|
||||
}
|
||||
justAdded = false;
|
||||
needsCannedAnimation = false;
|
||||
}
|
||||
|
||||
protected void onYTranslationAnimationFinished(View view) {
|
||||
if (hidden) {
|
||||
view.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public class AnimationFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private void combineFilter(AnimationFilter filter) {
|
||||
public void combineFilter(AnimationFilter filter) {
|
||||
animateAlpha |= filter.animateAlpha;
|
||||
animateX |= filter.animateX;
|
||||
animateY |= filter.animateY;
|
||||
@@ -134,7 +134,7 @@ public class AnimationFilter {
|
||||
hasDelays |= filter.hasDelays;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
public void reset() {
|
||||
animateAlpha = false;
|
||||
animateX = false;
|
||||
animateY = false;
|
||||
|
||||
@@ -213,7 +213,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|
||||
mDividers.add(newIndex, divider);
|
||||
|
||||
updateGroupOverflow();
|
||||
row.setIconTransformationAmount(0, false /* isLastChild */);
|
||||
row.setContentTransformationAmount(0, false /* isLastChild */);
|
||||
}
|
||||
|
||||
public void removeNotification(ExpandableNotificationRow row) {
|
||||
|
||||
@@ -99,36 +99,6 @@ public class ViewState {
|
||||
// don't do anything with it
|
||||
return;
|
||||
}
|
||||
boolean becomesInvisible = this.alpha == 0.0f || this.hidden;
|
||||
boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
|
||||
if (animatingAlpha) {
|
||||
updateAlphaAnimation(view);
|
||||
} else if (view.getAlpha() != this.alpha) {
|
||||
// apply layer type
|
||||
boolean becomesFullyVisible = this.alpha == 1.0f;
|
||||
boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
|
||||
&& view.hasOverlappingRendering();
|
||||
int layerType = view.getLayerType();
|
||||
int newLayerType = newLayerTypeIsHardware
|
||||
? View.LAYER_TYPE_HARDWARE
|
||||
: View.LAYER_TYPE_NONE;
|
||||
if (layerType != newLayerType) {
|
||||
view.setLayerType(newLayerType, null);
|
||||
}
|
||||
|
||||
// apply alpha
|
||||
view.setAlpha(this.alpha);
|
||||
}
|
||||
|
||||
// apply visibility
|
||||
int oldVisibility = view.getVisibility();
|
||||
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
|
||||
if (newVisibility != oldVisibility) {
|
||||
if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
|
||||
// We don't want views to change visibility when they are animating to GONE
|
||||
view.setVisibility(newVisibility);
|
||||
}
|
||||
}
|
||||
|
||||
// apply xTranslation
|
||||
boolean animatingX = isAnimating(view, TAG_ANIMATOR_TRANSLATION_X);
|
||||
@@ -163,6 +133,53 @@ public class ViewState {
|
||||
if (view.getScaleY() != this.scaleY) {
|
||||
view.setScaleY(this.scaleY);
|
||||
}
|
||||
|
||||
boolean becomesInvisible = this.alpha == 0.0f || (this.hidden && !isAnimating(view));
|
||||
boolean animatingAlpha = isAnimating(view, TAG_ANIMATOR_ALPHA);
|
||||
if (animatingAlpha) {
|
||||
updateAlphaAnimation(view);
|
||||
} else if (view.getAlpha() != this.alpha) {
|
||||
// apply layer type
|
||||
boolean becomesFullyVisible = this.alpha == 1.0f;
|
||||
boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
|
||||
&& view.hasOverlappingRendering();
|
||||
int layerType = view.getLayerType();
|
||||
int newLayerType = newLayerTypeIsHardware
|
||||
? View.LAYER_TYPE_HARDWARE
|
||||
: View.LAYER_TYPE_NONE;
|
||||
if (layerType != newLayerType) {
|
||||
view.setLayerType(newLayerType, null);
|
||||
}
|
||||
|
||||
// apply alpha
|
||||
view.setAlpha(this.alpha);
|
||||
}
|
||||
|
||||
// apply visibility
|
||||
int oldVisibility = view.getVisibility();
|
||||
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
|
||||
if (newVisibility != oldVisibility) {
|
||||
if (!(view instanceof ExpandableView) || !((ExpandableView) view).willBeGone()) {
|
||||
// We don't want views to change visibility when they are animating to GONE
|
||||
view.setVisibility(newVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAnimating(View view) {
|
||||
if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_X)) {
|
||||
return true;
|
||||
}
|
||||
if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Y)) {
|
||||
return true;
|
||||
}
|
||||
if (isAnimating(view, TAG_ANIMATOR_TRANSLATION_Z)) {
|
||||
return true;
|
||||
}
|
||||
if (isAnimating(view, TAG_ANIMATOR_ALPHA)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAnimating(View view, int tag) {
|
||||
@@ -482,7 +499,7 @@ public class ViewState {
|
||||
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
|
||||
child.setTag(TAG_START_TRANSLATION_Y, null);
|
||||
child.setTag(TAG_END_TRANSLATION_Y, null);
|
||||
onYTranslationAnimationFinished();
|
||||
onYTranslationAnimationFinished(child);
|
||||
}
|
||||
});
|
||||
startAnimator(animator, listener);
|
||||
@@ -491,7 +508,10 @@ public class ViewState {
|
||||
child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
|
||||
}
|
||||
|
||||
protected void onYTranslationAnimationFinished() {
|
||||
protected void onYTranslationAnimationFinished(View view) {
|
||||
if (hidden) {
|
||||
view.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void startAnimator(Animator animator, AnimatorListenerAdapter listener) {
|
||||
|
||||
Reference in New Issue
Block a user