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

Commit 85bebef2 authored by Ioana Alexandru's avatar Ioana Alexandru
Browse files

[Notif redesign] Animate top line in group header expansion

This change introduces a gradual transition when dragging to expand a
group, so the top line doesn't just jump to its centered position
when the expansion is done.

The on-click transition is not affected (i.e. it's still jumpy).

Bug: 378660052
Test: visual test
Flag: android.app.notifications_redesign_templates
Change-Id: I21ef172ba5ad14404e1c863c209a35bada3790d4
parent 53d05392
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.view;

import static android.app.Flags.notificationsRedesignTemplates;
import static android.util.MathUtils.abs;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

@@ -60,6 +61,7 @@ public class NotificationHeaderView extends RelativeLayout {
    private boolean mEntireHeaderClickable;
    private boolean mExpandOnlyOnButton;
    private boolean mAcceptAllTouches;
    private float mTopLineTranslation;

    ViewOutlineProvider mProvider = new ViewOutlineProvider() {
        @Override
@@ -205,6 +207,39 @@ public class NotificationHeaderView extends RelativeLayout {
        mExpandButton.setLayoutParams(lp);
    }

    /** The view containing the app name, timestamp etc at the top of the notification. */
    public NotificationTopLineView getTopLineView() {
        return mTopLineView;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        measureTopLineTranslation();
    }

    private void measureTopLineTranslation() {
        if (!notificationsRedesignTemplates()) {
            return;
        }

        // When the top line is centered (see centerTopLine), its height is MATCH_PARENT
        int parentHeight = getMeasuredHeight();
        // When the top line is top-aligned, its height is WRAP_CONTENT
        float wrapContentHeight = mTopLineView.getMeasuredHeight();
        // Calculate the translation needed between the two alignments
        final MarginLayoutParams lp = (MarginLayoutParams) mTopLineView.getLayoutParams();
        mTopLineTranslation = abs((parentHeight - wrapContentHeight) / 2f - lp.topMargin);
    }

    /**
     * The vertical translation necessary between the two positions of the top line, to be used in
     * the animation. See also {@link this#centerTopLine(boolean)}.
     */
    public float getTopLineTranslation() {
        return mTopLineTranslation;
    }

    /**
     * This is used to make the low-priority header show the bolded text of a title.
     *
+14 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ public class NotificationChildrenContainer extends ViewGroup
    private NotificationHeaderViewWrapper mMinimizedGroupHeaderWrapper;
    private NotificationGroupingUtil mGroupingUtil;
    private ViewState mHeaderViewState;
    private ViewState mTopLineViewState;
    private int mClipBottomAmount;
    private boolean mIsMinimized;
    private OnClickListener mHeaderClickListener;
@@ -884,6 +885,16 @@ public class NotificationChildrenContainer extends ViewGroup
            // The hiding is done automatically by the alpha, otherwise we'll pick it up again
            // in the next frame with the initFrom call above and have an invisible header
            mHeaderViewState.hidden = false;

            if (notificationsRedesignTemplates()) {
                if (mTopLineViewState == null) {
                    mTopLineViewState = new ViewState();
                }
                mTopLineViewState.initFrom(mGroupHeader);
                mTopLineViewState.setYTranslation(
                        mGroupHeader.getTopLineTranslation() * expandFactor);
                mTopLineViewState.hidden = false;
            }
        }
    }

@@ -976,6 +987,9 @@ public class NotificationChildrenContainer extends ViewGroup
        if (mHeaderViewState != null) {
            mHeaderViewState.applyToView(mGroupHeader);
        }
        if (notificationsRedesignTemplates() && mTopLineViewState != null) {
            mTopLineViewState.applyToView(mGroupHeader.getTopLineView());
        }
        updateChildrenClipping();
    }

+12 −0
Original line number Diff line number Diff line
@@ -6678,10 +6678,22 @@ public class NotificationStackScrollLayout
        }
        NotificationHeaderView header = childrenContainer.getGroupHeader();
        if (header != null) {
            resetYTranslation(header.getTopLineView());
            header.centerTopLine(expanded);
        }
    }

    /**
     * Reset the y translation of the {@code view} via the {@link ViewState}, to ensure that the
     * animation state is updated correctly.
     */
    private static void resetYTranslation(View view) {
        ViewState viewState = new ViewState();
        viewState.initFrom(view);
        viewState.setYTranslation(0);
        viewState.applyToView(view);
    }

    private final ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
        @Override
        public ExpandableView getChildAtPosition(float touchX, float touchY) {