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

Commit a64892c5 authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes I6da03a50,I4a444111,I21ef172b into main

* changes:
  Clean up NotificationChildrenContainer
  [Notif redesign] Animate expander alignment in group header expansion
  [Notif redesign] Animate top line in group header expansion
parents 79988956 1f32e86b
Loading
Loading
Loading
Loading
+49 −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,8 @@ public class NotificationHeaderView extends RelativeLayout {
    private boolean mEntireHeaderClickable;
    private boolean mExpandOnlyOnButton;
    private boolean mAcceptAllTouches;
    private float mTopLineTranslation;
    private float mExpandButtonTranslation;

    ViewOutlineProvider mProvider = new ViewOutlineProvider() {
        @Override
@@ -205,6 +208,52 @@ 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;
    }

    /** The view containing the button to expand the notification. */
    public NotificationExpandButton getExpandButton() {
        return mExpandButton;
    }

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

        if (notificationsRedesignTemplates()) {
            mTopLineTranslation = measureCenterTranslation(mTopLineView);
            mExpandButtonTranslation = measureCenterTranslation(mExpandButton);
        }
    }

    private float measureCenterTranslation(View view) {
        // When the view is centered (see centerTopLine), its height is MATCH_PARENT
        int parentHeight = getMeasuredHeight();
        // When the view is top-aligned, its height is WRAP_CONTENT
        float wrapContentHeight = view.getMeasuredHeight();
        // Calculate the translation needed between the two alignments
        final MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
        return 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 NotificationHeaderView#centerTopLine(boolean)}.
     */
    public float getTopLineTranslation() {
        return mTopLineTranslation;
    }

    /**
     * The vertical translation necessary between the two positions of the expander, to be used in
     * the animation. See also {@link NotificationHeaderView#centerTopLine(boolean)}.
     */
    public float getExpandButtonTranslation() {
        return mExpandButtonTranslation;
    }

    /**
     * This is used to make the low-priority header show the bolded text of a title.
     *
+1 −10
Original line number Diff line number Diff line
@@ -1246,15 +1246,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        }
    }

    /**
     * Prepares expansion changed.
     */
    public void prepareExpansionChanged() {
        if (mIsSummaryWithChildren) {
            mChildrenContainer.prepareExpansionChanged();
        }
    }

    /**
     * Starts child animations.
     */
@@ -1569,7 +1560,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
        // Let's update our childrencontainer. This is intentionally not guarded with
        // mIsSummaryWithChildren since we might have had children but not anymore.
        if (mChildrenContainer != null) {
            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.getSbn());
            mChildrenContainer.reInflateViews(mExpandClickListener);
        }
        if (mGuts != null) {
            NotificationGuts oldGuts = mGuts;
+40 −48
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ public class NotificationChildrenContainer extends ViewGroup
    static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
    public static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
    private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
        private final AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();

        @Override
        public AnimationFilter getAnimationFilter() {
@@ -123,6 +123,8 @@ public class NotificationChildrenContainer extends ViewGroup
    private NotificationHeaderViewWrapper mMinimizedGroupHeaderWrapper;
    private NotificationGroupingUtil mGroupingUtil;
    private ViewState mHeaderViewState;
    private ViewState mTopLineViewState;
    private ViewState mExpandButtonViewState;
    private int mClipBottomAmount;
    private boolean mIsMinimized;
    private OnClickListener mHeaderClickListener;
@@ -138,7 +140,7 @@ public class NotificationChildrenContainer extends ViewGroup
    private float mHeaderVisibleAmount = 1.0f;
    private int mUntruncatedChildCount;
    private boolean mContainingNotificationIsFaded = false;
    private RoundableState mRoundableState;
    private final RoundableState mRoundableState;
    private int mMinSingleLineHeight;

    private NotificationChildrenContainerLogger mLogger;
@@ -446,7 +448,7 @@ public class NotificationChildrenContainer extends ViewGroup
        }
        mGroupHeaderWrapper.setExpanded(mChildrenExpanded);
        mGroupHeaderWrapper.onContentUpdated(mContainingNotification);
        recreateLowPriorityHeader(builder, isConversation);
        recreateLowPriorityHeader(builder);
        updateHeaderVisibility(false /* animate */);
        updateChildrenAppearance();
        Trace.endSection();
@@ -559,7 +561,7 @@ public class NotificationChildrenContainer extends ViewGroup
     * @param builder a builder to reuse. Otherwise the builder will be recovered.
     */
    @VisibleForTesting
    void recreateLowPriorityHeader(Notification.Builder builder, boolean isConversation) {
    void recreateLowPriorityHeader(Notification.Builder builder) {
        AsyncGroupHeaderViewInflation.assertInLegacyMode();
        RemoteViews header;
        StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
@@ -866,10 +868,7 @@ public class NotificationChildrenContainer extends ViewGroup
            }
        }
        if (mGroupHeader != null) {
            if (mHeaderViewState == null) {
                mHeaderViewState = new ViewState();
            }
            mHeaderViewState.initFrom(mGroupHeader);
            mHeaderViewState = initStateForGroupHeader(mHeaderViewState);

            if (mContainingNotification.hasExpandingChild()) {
                // Not modifying translationZ during expand animation.
@@ -881,38 +880,33 @@ public class NotificationChildrenContainer extends ViewGroup
            }
            mHeaderViewState.setYTranslation(mCurrentHeaderTranslation);
            mHeaderViewState.setAlpha(mHeaderVisibleAmount);
            // 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()) {
                mTopLineViewState = initStateForGroupHeader(mTopLineViewState);
                mTopLineViewState.setYTranslation(
                        mGroupHeader.getTopLineTranslation() * expandFactor);

                mExpandButtonViewState = initStateForGroupHeader(mExpandButtonViewState);
                mExpandButtonViewState.setYTranslation(
                        mGroupHeader.getExpandButtonTranslation() * expandFactor);
            }
        }
    }

    /**
     * When moving into the bottom stack, the bottom visible child in an expanded group adjusts its
     * height, children in the group after this are gone.
     *
     * @param child        the child who's height to adjust.
     * @param parentHeight the height of the parent.
     * @param childState   the state to update.
     * @param yPosition    the yPosition of the view.
     * @return true if children after this one should be hidden.
     * Initialise a new ViewState for the group header or its children, or update and return
     * {@code existingState} if not null.
     */
    private boolean updateChildStateForExpandedGroup(
            ExpandableNotificationRow child,
            int parentHeight,
            ExpandableViewState childState,
            int yPosition) {
        final int top = yPosition + child.getClipTopAmount();
        final int intrinsicHeight = child.getIntrinsicHeight();
        final int bottom = top + intrinsicHeight;
        int newHeight = intrinsicHeight;
        if (bottom >= parentHeight) {
            // Child is either clipped or gone
            newHeight = Math.max((parentHeight - top), 0);
        }
        childState.hidden = newHeight == 0;
        childState.height = newHeight;
        return childState.height != intrinsicHeight && !childState.hidden;
    private ViewState initStateForGroupHeader(ViewState existingState) {
        ViewState viewState = existingState;
        if (viewState == null) {
            viewState = new ViewState();
        }
        viewState.initFrom(mGroupHeader);
        // 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
        viewState.hidden = false;
        return viewState;
    }

    @VisibleForTesting
@@ -976,6 +970,14 @@ public class NotificationChildrenContainer extends ViewGroup
        if (mHeaderViewState != null) {
            mHeaderViewState.applyToView(mGroupHeader);
        }
        if (notificationsRedesignTemplates()) {
            if (mTopLineViewState != null) {
                mTopLineViewState.applyToView(mGroupHeader.getTopLineView());
            }
            if (mExpandButtonViewState != null) {
                mExpandButtonViewState.applyToView(mGroupHeader.getExpandButton());
            }
        }
        updateChildrenClipping();
    }

@@ -1010,7 +1012,7 @@ public class NotificationChildrenContainer extends ViewGroup
    }

    @Override
    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    protected boolean drawChild(@NonNull Canvas canvas, View child, long drawingTime) {
        boolean isCanvasChanged = false;

        Path clipPath = mChildClipPath;
@@ -1062,16 +1064,6 @@ public class NotificationChildrenContainer extends ViewGroup
        }
    }


    /**
     * This is called when the children expansion has changed and positions the children properly
     * for an appear animation.
     */
    public void prepareExpansionChanged() {
        // TODO: do something that makes sense, like placing the invisible views correctly
        return;
    }

    /**
     * Animate to a given state.
     */
@@ -1478,7 +1470,7 @@ public class NotificationChildrenContainer extends ViewGroup
        return mIsMinimized && !mContainingNotification.isExpanded();
    }

    public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
    public void reInflateViews(OnClickListener listener) {
        if (!AsyncGroupHeaderViewInflation.isEnabled()) {
            // When Async header inflation is enabled, we do not reinflate headers because they are
            // inflated from the background thread
@@ -1567,7 +1559,7 @@ public class NotificationChildrenContainer extends ViewGroup
        mIsMinimized = isMinimized;
        if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
            if (!AsyncGroupHeaderViewInflation.isEnabled()) {
                recreateLowPriorityHeader(null /* existingBuilder */, mIsConversation);
                recreateLowPriorityHeader(null /* existingBuilder */);
            }
            updateHeaderVisibility(false /* animate */);
        }
+13 −0
Original line number Diff line number Diff line
@@ -6683,10 +6683,23 @@ public class NotificationStackScrollLayout
        }
        NotificationHeaderView header = childrenContainer.getGroupHeader();
        if (header != null) {
            resetYTranslation(header.getTopLineView());
            resetYTranslation(header.getExpandButton());
            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) {
+0 −4
Original line number Diff line number Diff line
@@ -468,10 +468,6 @@ public class StackStateAnimator {
                if (isFullySwipedOut) {
                    changingView.removeFromTransientContainer();
                }
            } else if (event.animationType == NotificationStackScrollLayout
                    .AnimationEvent.ANIMATION_TYPE_GROUP_EXPANSION_CHANGED) {
                ExpandableNotificationRow row = (ExpandableNotificationRow) event.mChangingView;
                row.prepareExpansionChanged();
            } else if (event.animationType == ANIMATION_TYPE_HEADS_UP_CYCLING_IN) {
                mHeadsUpAppearChildren.add(changingView);

Loading