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

Commit 11298830 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Fade notification contents when expanding/contracting

Bug: 15284460
Change-Id: If0f18e0b8fc9e7410cc6ef2a7976bcec49a6eb6e
parent 23a0bf3c
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -212,13 +212,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
        return mShowingPublic ? mRowMinHeight : mMaxExpandHeight;
    }

    /**
     * @return the potential height this view could expand in addition.
     */
    public int getExpandPotential() {
        return getIntrinsicHeight() - getActualHeight();
    }

    @Override
    public boolean isContentExpandable() {
        NotificationContentView showingLayout = getShowingLayout();
+67 −20
Original line number Diff line number Diff line
@@ -17,12 +17,16 @@
package com.android.systemui.statusbar;

import android.content.Context;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;

import com.android.systemui.R;

/**
@@ -32,6 +36,8 @@ import com.android.systemui.R;
 */
public class NotificationContentView extends FrameLayout {

    private static final long ANIMATION_DURATION_LENGTH = 170;

    private final Rect mClipBounds = new Rect();

    private View mContractedChild;
@@ -41,10 +47,17 @@ public class NotificationContentView extends FrameLayout {
    private int mClipTopAmount;
    private int mActualHeight;

    private final Interpolator mLinearInterpolator = new LinearInterpolator();

    private boolean mContractedVisible = true;

    private Paint mFadePaint = new Paint();

    public NotificationContentView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
        mActualHeight = mSmallHeight;
        mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
    }

    @Override
@@ -60,7 +73,7 @@ public class NotificationContentView extends FrameLayout {
        sanitizeContractedLayoutParams(child);
        addView(child);
        mContractedChild = child;
        selectLayout();
        selectLayout(false /* animate */, true /* force */);
    }

    public void setExpandedChild(View child) {
@@ -69,12 +82,12 @@ public class NotificationContentView extends FrameLayout {
        }
        addView(child);
        mExpandedChild = child;
        selectLayout();
        selectLayout(false /* animate */, true /* force */);
    }

    public void setActualHeight(int actualHeight) {
        mActualHeight = actualHeight;
        selectLayout();
        selectLayout(true /* animate */, false /* force */);
        updateClipping();
    }

@@ -104,26 +117,60 @@ public class NotificationContentView extends FrameLayout {
        contractedChild.setLayoutParams(lp);
    }

    private void selectLayout() {
        if (mActualHeight <= mSmallHeight || mExpandedChild == null) {
            if (mContractedChild != null && mContractedChild.getVisibility() != View.VISIBLE) {
                mContractedChild.setVisibility(View.VISIBLE);
    private void selectLayout(boolean animate, boolean force) {
        if (mContractedChild == null) {
            return;
        }
            if (mExpandedChild != null && mExpandedChild.getVisibility() != View.INVISIBLE) {
                mExpandedChild.setVisibility(View.INVISIBLE);
        boolean showContractedChild = showContractedChild();
        if (showContractedChild != mContractedVisible || force) {
            if (animate && mExpandedChild != null) {
                runSwitchAnimation(showContractedChild);
            } else if (mExpandedChild != null) {
                mContractedChild.setVisibility(showContractedChild ? View.VISIBLE : View.INVISIBLE);
                mContractedChild.setAlpha(showContractedChild ? 1f : 0f);
                mExpandedChild.setVisibility(showContractedChild ? View.INVISIBLE : View.VISIBLE);
                mExpandedChild.setAlpha(showContractedChild ? 0f : 1f);
            }
        } else {
            if (mExpandedChild.getVisibility() != View.VISIBLE) {
                mExpandedChild.setVisibility(View.VISIBLE);
        }
            if (mContractedChild != null && mContractedChild.getVisibility() != View.INVISIBLE) {
                mContractedChild.setVisibility(View.INVISIBLE);
        mContractedVisible = showContractedChild;
    }

    private void runSwitchAnimation(final boolean showContractedChild) {
        mContractedChild.setVisibility(View.VISIBLE);
        mExpandedChild.setVisibility(View.VISIBLE);
        mContractedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
        mExpandedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
        setLayerType(LAYER_TYPE_HARDWARE, null);
        mContractedChild.animate()
                .alpha(showContractedChild ? 1f : 0f)
                .setDuration(ANIMATION_DURATION_LENGTH)
                .setInterpolator(mLinearInterpolator);
        mExpandedChild.animate()
                .alpha(showContractedChild ? 0f : 1f)
                .setDuration(ANIMATION_DURATION_LENGTH)
                .setInterpolator(mLinearInterpolator)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
                        mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
                        setLayerType(LAYER_TYPE_NONE, null);
                        mContractedChild.setVisibility(showContractedChild
                                ? View.VISIBLE
                                : View.INVISIBLE);
                        mExpandedChild.setVisibility(showContractedChild
                                ? View.INVISIBLE
                                : View.VISIBLE);
                    }
                });
    }

    private boolean showContractedChild() {
        return mActualHeight <= mSmallHeight || mExpandedChild == null;
    }

    public void notifyContentUpdated() {
        selectLayout();
        selectLayout(false /* animate */, true /* force */);
    }

    public boolean isContentExpandable() {