Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b5beb01 authored by Selim Cinek's avatar Selim Cinek
Browse files

Added appear and disappear animations for the shelf icons

The icons now animate in and out of the shelf nicer.
Also fixed that the regular animation was played when in the shelf.

Test: Add notifications, observe animation in statusbar
Bug: 32437839
Change-Id: Id003fee1508b8c18a933d38faf93541be21baffd
parent 49014f85
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.systemui.statusbar;

import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState;

import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
@@ -157,6 +155,7 @@ public class NotificationShelf extends ActivatableNotificationView {
            mShelfState.shadowAlpha = 1.0f;
            mShelfState.isBottomClipped = false;
            mShelfState.hideSensitive = false;
            mShelfState.xTranslation = getTranslationX();
            if (mNotGoneIndex != -1) {
                mShelfState.notGoneIndex = Math.min(mShelfState.notGoneIndex, mNotGoneIndex);
            }
@@ -173,7 +172,7 @@ public class NotificationShelf extends ActivatableNotificationView {
     * the icons from the notification area into the shelf.
     */
    public void updateAppearance() {
        WeakHashMap<View, IconState> iconStates =
        WeakHashMap<View, NotificationIconContainer.IconState> iconStates =
                mShelfIcons.resetViewStates();
        float numIconsInShelf = 0.0f;
        int shelfIndex = mAmbientState.getShelfIndex();
@@ -196,7 +195,7 @@ public class NotificationShelf extends ActivatableNotificationView {
            }
            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
            StatusBarIconView icon = row.getEntry().expandedIcon;
            IconState iconState = iconStates.get(icon);
            NotificationIconContainer.IconState iconState = iconStates.get(icon);
            float notificationClipEnd;
            float shelfStart = getTranslationY();
            boolean aboveShelf = row.getTranslationZ() > mAmbientState.getBaseZHeight();
@@ -255,8 +254,9 @@ public class NotificationShelf extends ActivatableNotificationView {
        }
    }

    private void updateIconAppearance(ExpandableNotificationRow row, IconState iconState,
            StatusBarIconView icon, float expandAmount) {
    private void updateIconAppearance(ExpandableNotificationRow row,
            NotificationIconContainer.IconState iconState, StatusBarIconView icon,
            float expandAmount) {
        // Let calculate how much the view is in the shelf
        float viewStart = row.getTranslationY();
        int transformHeight = row.getActualHeight() + mPaddingBetweenElements;
+63 −43
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Notification;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -68,7 +67,7 @@ public class StatusBarIconView extends AnimatedImageView {
            return object.getIconAppearAmount();
        }
    };
    private static final Property<StatusBarIconView, Float> DOT_APPEAR_AMOUNG
    private static final Property<StatusBarIconView, Float> DOT_APPEAR_AMOUNT
            = new FloatProperty<StatusBarIconView>("dot_appear_amount") {

        @Override
@@ -440,9 +439,23 @@ public class StatusBarIconView extends AnimatedImageView {
        mDotPaint.setColor(iconTint);
    }

    public void setVisibleState(int visibleState) {
    public void setVisibleState(int state) {
        setVisibleState(state, true /* animate */, null /* endRunnable */);
    }

    public void setVisibleState(int state, boolean animate) {
        setVisibleState(state, animate, null);
    }

    @Override
    public boolean hasOverlappingRendering() {
        return false;
    }

    public void setVisibleState(int visibleState, boolean animate, Runnable endRunnable) {
        if (visibleState != mVisibleState) {
            mVisibleState = visibleState;
            if (animate) {
                if (mIconAppearAnimator != null) {
                    mIconAppearAnimator.cancel();
                }
@@ -460,6 +473,9 @@ public class StatusBarIconView extends AnimatedImageView {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mIconAppearAnimator = null;
                        if (endRunnable != null) {
                            endRunnable.run();
                        }
                    }
                });
                mIconAppearAnimator.start();
@@ -473,7 +489,7 @@ public class StatusBarIconView extends AnimatedImageView {
                    targetAmount = 1.0f;
                    interpolator = Interpolators.LINEAR_OUT_SLOW_IN;
                }
            mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNG,
                mDotAnimator = ObjectAnimator.ofFloat(this, DOT_APPEAR_AMOUNT,
                        targetAmount);
                mDotAnimator.setInterpolator(interpolator);
                mDotAnimator.setDuration(100);
@@ -484,10 +500,14 @@ public class StatusBarIconView extends AnimatedImageView {
                    }
                });
                mDotAnimator.start();
            } else {
                setIconAppearAmount(visibleState == STATE_ICON ? 1.0f : 0.0f);
                setDotAppearAmount(visibleState == STATE_DOT ? 1.0f : 0.0f);
            }
        }
    }

    public void setIconAppearAmount(Float iconAppearAmount) {
    public void setIconAppearAmount(float iconAppearAmount) {
        mIconAppearAmount = iconAppearAmount;
        invalidate();
    }
+7 −4
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ public class NotificationIconAreaController {
    private PhoneStatusBar mPhoneStatusBar;
    protected View mNotificationIconArea;
    private NotificationIconContainer mNotificationIcons;
    private NotificationIconContainer mNotificationIconsScroller;
    private NotificationIconContainer mShelfIcons;
    private final Rect mTintArea = new Rect();
    private NotificationStackScrollLayout mNotificationScrollLayout;
    private Context mContext;
@@ -65,7 +65,7 @@ public class NotificationIconAreaController {
                R.id.notificationIcons);

        NotificationShelf shelf = mPhoneStatusBar.getNotificationShelf();
        mNotificationIconsScroller = shelf.getShelfIcons();
        mShelfIcons = shelf.getShelfIcons();
        shelf.setCollapsedIcons(mNotificationIcons);

        mNotificationScrollLayout = mPhoneStatusBar.getNotificationScrollLayout();
@@ -147,8 +147,7 @@ public class NotificationIconAreaController {
    public void updateNotificationIcons(NotificationData notificationData) {

        updateIconsForLayout(notificationData, entry -> entry.icon, mNotificationIcons);
        updateIconsForLayout(notificationData, entry -> entry.expandedIcon,
                mNotificationIconsScroller);
        updateIconsForLayout(notificationData, entry -> entry.expandedIcon, mShelfIcons);

        applyNotificationIconsTint();
        ArrayList<NotificationData.Entry> activeNotifications
@@ -207,11 +206,14 @@ public class NotificationIconAreaController {
        final LinearLayout.LayoutParams params = generateIconLayoutParams();
        for (int i = 0; i < toShow.size(); i++) {
            View v = toShow.get(i);
            // The view might still be transiently added if it was just removed and added again
            hostLayout.removeTransientView(v);
            if (v.getParent() == null) {
                hostLayout.addView(v, i, params);
            }
        }

        hostLayout.setChangingViewPositions(true);
        // Re-sort notification icons
        final int childCount = hostLayout.getChildCount();
        for (int i = 0; i < childCount; i++) {
@@ -223,6 +225,7 @@ public class NotificationIconAreaController {
            hostLayout.removeView(expected);
            hostLayout.addView(expected, i);
        }
        hostLayout.setChangingViewPositions(false);
    }

    /**
+83 −8
Original line number Diff line number Diff line
@@ -40,14 +40,24 @@ import java.util.WeakHashMap;
public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
    private static final String TAG = "NotificationIconContainer";
    private static final boolean DEBUG = false;
    private static final AnimationFilter DOT_ANIMATION_FILTER = new AnimationFilter().animateX();
    private static final AnimationProperties DOT_ANIMATION_PROPERTIES = new AnimationProperties() {
        private AnimationFilter mAnimationFilter = new AnimationFilter().animateX();

        @Override
        public AnimationFilter getAnimationFilter() {
            return DOT_ANIMATION_FILTER;
            return mAnimationFilter;
        }
    }.setDuration(200);
    
    private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();

        @Override
        public AnimationFilter getAnimationFilter() {
            return mAnimationFilter;
        }
    }.setDuration(200).setDelay(50);

    private boolean mShowAllIcons = true;
    private WeakHashMap<View, IconState> mIconStates = new WeakHashMap<>();
    private int mDotPadding;
@@ -55,6 +65,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
    private int mActualLayoutWidth = -1;
    private float mActualPaddingEnd = -1;
    private float mActualPaddingStart = -1;
    private boolean mChangingViewPositions;
    private int mAnimationStartIndex = -1;

    public NotificationIconContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -109,18 +121,60 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
                childState.applyToView(child);
            }
        }
        mAnimationStartIndex = -1;
    }

    @Override
    public void onViewAdded(View child) {
        super.onViewAdded(child);
        if (!mChangingViewPositions) {
            mIconStates.put(child, new IconState());
        }
        int childIndex = indexOfChild(child);
        if (childIndex < getChildCount() - 1
            && mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
            if (mAnimationStartIndex < 0) {
                mAnimationStartIndex = childIndex;
            } else {
                mAnimationStartIndex = Math.min(mAnimationStartIndex, childIndex);
            }
        }
    }

    @Override
    public void onViewRemoved(View child) {
        super.onViewRemoved(child);
        if (child instanceof StatusBarIconView) {
            final StatusBarIconView icon = (StatusBarIconView) child;
            if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
                    && child.getVisibility() == VISIBLE) {
                int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
                if (mAnimationStartIndex < 0) {
                    mAnimationStartIndex = animationStartIndex;
                } else {
                    mAnimationStartIndex = Math.min(mAnimationStartIndex, animationStartIndex);
                }
            }
            if (!mChangingViewPositions) {
                mIconStates.remove(child);
                addTransientView(icon, 0);
                icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
                        () -> removeTransientView(icon));
            }
        }
    }

    /**
     * Finds the first view with a translation bigger then a given value
     */
    private int findFirstViewIndexAfter(float translationX) {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            if (view.getTranslationX() > translationX) {
                return i;
            }
        }
        return getChildCount();
    }

    public WeakHashMap<View, IconState> resetViewStates() {
@@ -128,6 +182,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
            View view = getChildAt(i);
            ViewState iconState = mIconStates.get(view);
            iconState.initFrom(view);
            iconState.alpha = 1.0f;
        }
        return mIconStates;
    }
@@ -246,21 +301,41 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
        return mActualLayoutWidth;
    }

    public static class IconState extends ViewState {
    public void setChangingViewPositions(boolean changingViewPositions) {
        mChangingViewPositions = changingViewPositions;
    }

    public class IconState extends ViewState {
        public float iconAppearAmount = 1.0f;
        public int visibleState;
        public boolean justAdded = true;

        @Override
        public void applyToView(View view) {
            if (view instanceof StatusBarIconView) {
                StatusBarIconView icon = (StatusBarIconView) view;
                if (visibleState != icon.getVisibleState()) {
                AnimationProperties animationProperties = DOT_ANIMATION_PROPERTIES;
                if (justAdded) {
                    super.applyToView(icon);
                    icon.setAlpha(0.0f);
                    icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, false /* animate */);
                    animationProperties = ADD_ICON_PROPERTIES;
                }
                boolean animate = visibleState != icon.getVisibleState() || justAdded;
                if (!animate && mAnimationStartIndex >= 0
                        && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
                            || visibleState != StatusBarIconView.STATE_HIDDEN)) {
                    int viewIndex = indexOfChild(view);
                    animate = viewIndex >= mAnimationStartIndex;
                }
                icon.setVisibleState(visibleState);
                    animateTo(icon, DOT_ANIMATION_PROPERTIES);
                if (animate) {
                    animateTo(icon, animationProperties);
                } else {
                    super.applyToView(view);
                }
            }
            justAdded = false;
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ public class ExpandableViewState extends ViewState {
        // start dark animation
        expandableView.setDark(this.dark, animationFilter.animateDark, properties.delay);

        if (properties.wasAdded(child)) {
        if (properties.wasAdded(child) && !hidden) {
            expandableView.performAddAnimation(properties.delay, properties.duration);
        }

Loading