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

Commit 9f2d21f3 authored by Selim Cinek's avatar Selim Cinek
Browse files

Improved the animations of the conversation badges

Previously the badges would just immediately disappear
without an animation. They are now animated when the
icon has finished animating.

Bug: 150905003
Test: add conversations, observe animations
Change-Id: I29e7389732bd5c22953dd7753d0feaae00297db0
parent 9ed6e045
Loading
Loading
Loading
Loading
+37 −2
Original line number Diff line number Diff line
@@ -46,7 +46,9 @@ public class CachingIconView extends ImageView {
    private boolean mForceHidden;
    private int mDesiredVisibility;
    private Consumer<Integer> mOnVisibilityChangedListener;
    private Consumer<Boolean> mOnForceHiddenChangedListener;
    private int mIconColor;
    private boolean mWillBeForceHidden;

    @UnsupportedAppUsage
    public CachingIconView(Context context, @Nullable AttributeSet attrs) {
@@ -185,10 +187,18 @@ public class CachingIconView extends ImageView {

    /**
     * Set the icon to be forcibly hidden, even when it's visibility is changed to visible.
     * This is necessary since we still want to keep certain views hidden when their visibility
     * is modified from other sources like the shelf.
     */
    public void setForceHidden(boolean forceHidden) {
        if (forceHidden != mForceHidden) {
            mForceHidden = forceHidden;
            mWillBeForceHidden = false;
            updateVisibility();
            if (mOnForceHiddenChangedListener != null) {
                mOnForceHiddenChangedListener.accept(forceHidden);
            }
        }
    }

    @Override
@@ -211,6 +221,15 @@ public class CachingIconView extends ImageView {
        mOnVisibilityChangedListener = listener;
    }

    public void setOnForceHiddenChangedListener(Consumer<Boolean> listener) {
        mOnForceHiddenChangedListener = listener;
    }


    public boolean isForceHidden() {
        return mForceHidden;
    }

    @RemotableViewMethod
    public void setOriginalIconColor(int color) {
        mIconColor = color;
@@ -219,4 +238,20 @@ public class CachingIconView extends ImageView {
    public int getOriginalIconColor() {
        return mIconColor;
    }

    /**
     * @return if the view will be forceHidden after an animation
     */
    public boolean willBeForceHidden() {
        return mWillBeForceHidden;
    }

    /**
     * Set that this view will be force hidden after an animation
     *
     * @param forceHidden if it will be forcehidden
     */
    public void setWillBeForceHidden(boolean forceHidden) {
        mWillBeForceHidden = forceHidden;
    }
}
+62 −6
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.internal.widget;

import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_EXTERNAL;
import static com.android.internal.widget.MessagingGroup.IMAGE_DISPLAY_LOCATION_INLINE;
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN;
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT;

import android.annotation.AttrRes;
import android.annotation.NonNull;
@@ -106,7 +108,7 @@ public class ConversationLayout extends FrameLayout
    private CharSequence mNameReplacement;
    private boolean mIsCollapsed;
    private ImageResolver mImageResolver;
    private ImageView mConversationIcon;
    private CachingIconView mConversationIcon;
    private View mConversationIconContainer;
    private int mConversationIconTopPadding;
    private int mConversationIconTopPaddingExpandedGroup;
@@ -114,7 +116,7 @@ public class ConversationLayout extends FrameLayout
    private int mExpandedGroupMessagePaddingNoAppName;
    private TextView mConversationText;
    private View mConversationIconBadge;
    private ImageView mConversationIconBadgeBg;
    private CachingIconView mConversationIconBadgeBg;
    private Icon mLargeIcon;
    private View mExpandButtonContainer;
    private ViewGroup mExpandButtonAndContentContainer;
@@ -125,7 +127,7 @@ public class ConversationLayout extends FrameLayout
    private int mConversationAvatarSize;
    private int mConversationAvatarSizeExpanded;
    private CachingIconView mIcon;
    private View mImportanceRingView;
    private CachingIconView mImportanceRingView;
    private int mExpandedGroupSideMargin;
    private int mExpandedGroupSideMarginFacePile;
    private View mConversationFacePile;
@@ -187,9 +189,41 @@ public class ConversationLayout extends FrameLayout
        mConversationIconBadge = findViewById(R.id.conversation_icon_badge);
        mConversationIconBadgeBg = findViewById(R.id.conversation_icon_badge_bg);
        mIcon.setOnVisibilityChangedListener((visibility) -> {
            // Always keep the badge visibility in sync with the icon. This is necessary in cases

            // Let's hide the background directly or in an animated way
            boolean isGone = visibility == GONE;
            int oldVisibility = mConversationIconBadgeBg.getVisibility();
            boolean wasGone = oldVisibility == GONE;
            if (wasGone != isGone) {
                // Keep the badge gone state in sync with the icon. This is necessary in cases
                // Where the icon is being hidden externally like in group children.
                mConversationIconBadgeBg.animate().cancel();
                mConversationIconBadgeBg.setVisibility(visibility);
            }

            // Let's handle the importance ring which can also be be gone normally
            oldVisibility = mImportanceRingView.getVisibility();
            wasGone = oldVisibility == GONE;
            visibility = !mImportantConversation ? GONE : visibility;
            isGone = visibility == GONE;
            if (wasGone != isGone) {
                // Keep the badge visibility in sync with the icon. This is necessary in cases
                // Where the icon is being hidden externally like in group children.
            mConversationIconBadge.setVisibility(visibility);
                mImportanceRingView.animate().cancel();
                mImportanceRingView.setVisibility(visibility);
            }
        });
        // When the small icon is gone, hide the rest of the badge
        mIcon.setOnForceHiddenChangedListener((forceHidden) -> {
            animateViewForceHidden(mConversationIconBadgeBg, forceHidden);
            animateViewForceHidden(mImportanceRingView, forceHidden);
        });

        // When the conversation icon is gone, hide the whole badge
        mConversationIcon.setOnForceHiddenChangedListener((forceHidden) -> {
            animateViewForceHidden(mConversationIconBadgeBg, forceHidden);
            animateViewForceHidden(mImportanceRingView, forceHidden);
            animateViewForceHidden(mIcon, forceHidden);
        });
        mConversationText = findViewById(R.id.conversation_text);
        mExpandButtonContainer = findViewById(R.id.expand_button_container);
@@ -241,6 +275,28 @@ public class ConversationLayout extends FrameLayout
        });
    }

    private void animateViewForceHidden(CachingIconView view, boolean forceHidden) {
        boolean nowForceHidden = view.willBeForceHidden() || view.isForceHidden();
        if (forceHidden == nowForceHidden) {
            // We are either already forceHidden or will be
            return;
        }
        view.animate().cancel();
        view.setWillBeForceHidden(forceHidden);
        view.animate()
                .scaleX(forceHidden ? 0.5f : 1.0f)
                .scaleY(forceHidden ? 0.5f : 1.0f)
                .alpha(forceHidden ? 0.0f : 1.0f)
                .setInterpolator(forceHidden ? ALPHA_OUT : ALPHA_IN)
                .setDuration(160);
        if (view.getVisibility() != VISIBLE) {
            view.setForceHidden(forceHidden);
        } else {
            view.animate().withEndAction(() -> view.setForceHidden(forceHidden));
        }
        view.animate().start();
    }

    @RemotableViewMethod
    public void setAvatarReplacement(Icon icon) {
        mAvatarReplacement = icon;
+1 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import com.android.internal.R;
 */
public class MessagingPropertyAnimator implements View.OnLayoutChangeListener {
    private static final long APPEAR_ANIMATION_LENGTH = 210;
    private static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
    public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
    private static final int TAG_TOP_ANIMATOR = R.id.tag_top_animator;
    private static final int TAG_TOP = R.id.tag_top_override;
+5 −2
Original line number Diff line number Diff line
@@ -64,11 +64,12 @@
                android:layout_marginLeft="@dimen/conversation_badge_side_margin"
                android:layout_marginTop="@dimen/conversation_badge_side_margin"
            >
                <ImageView
                <com.android.internal.widget.CachingIconView
                    android:id="@+id/conversation_icon_badge_bg"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/conversation_badge_background"
                    android:forceHasOverlappingRendering="false"
                />
                <com.android.internal.widget.CachingIconView
                    android:id="@+id/icon"
@@ -76,13 +77,15 @@
                    android:layout_height="match_parent"
                    android:layout_margin="4dp"
                    android:layout_gravity="center"
                    android:forceHasOverlappingRendering="false"
                />
                <ImageView
                <com.android.internal.widget.CachingIconView
                    android:id="@+id/conversation_icon_badge_ring"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/conversation_badge_ring"
                    android:visibility="gone"
                    android:forceHasOverlappingRendering="false"
                />
            </FrameLayout>
        </FrameLayout>
+6 −1
Original line number Diff line number Diff line
@@ -136,7 +136,12 @@ class NotificationConversationTemplateViewWrapper constructor(

    override fun setShelfIconVisible(visible: Boolean) {
        if (conversationLayout.isImportantConversation) {
            if (conversationIcon.visibility != GONE) {
                conversationIcon.setForceHidden(visible);
                // We don't want the small icon to be hidden by the extended wrapper, as force
                // hiding the conversationIcon will already do that via its listener.
                return;
            }
        }
        super.setShelfIconVisible(visible)
    }