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

Commit 63075cc3 authored by Lyn Han's avatar Lyn Han Committed by Android (Google) Code Review
Browse files

Merge "Short shelf on lockscreen that animates width with transition to shade"

parents cb6178a2 9a52b474
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -337,11 +337,11 @@ class LockscreenShadeTransitionController @Inject constructor(
            if (field != value || forceApplyAmount) {
                field = value
                if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
                    nsslController.setTransitionToFullShadeAmount(field)
                    notificationPanelController.setTransitionToFullShadeAmount(field,
                            false /* animate */, 0 /* delay */)
                    qSDragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
                    nsslController.setTransitionToFullShadeAmount(field, qSDragProgress)
                    qS.setTransitionToFullShadeAmount(field, qSDragProgress)
                    notificationPanelController.setTransitionToFullShadeAmount(field,
                            false /* animate */, 0 /* delay */)
                    // TODO: appear media also in split shade
                    val mediaAmount = if (useSplitShade) 0f else field
                    mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
+110 −6
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar;

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

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -32,6 +34,7 @@ import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -45,6 +48,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
import com.android.systemui.util.Utils;

/**
 * A notification shelf view that is placed inside the notification scroller. It manages the
@@ -81,6 +85,11 @@ public class NotificationShelf extends ActivatableNotificationView implements
    private int mIndexOfFirstViewInShelf = -1;
    private float mCornerAnimationDistance;
    private NotificationShelfController mController;
    private int mActualWidth = -1;
    private boolean mUseSplitShade;

    /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */
    private float mFractionToShade;

    public NotificationShelf(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -122,13 +131,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
        layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
        setLayoutParams(layoutParams);

        int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
        final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
        mShelfIcons.setPadding(padding, 0, padding, 0);
        mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
        mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
        mCornerAnimationDistance = res.getDimensionPixelSize(
                R.dimen.notification_corner_animation_distance);

        // TODO(b/213480466)  enable short shelf on split shade
        mUseSplitShade = Utils.shouldUseSplitNotificationShade(mContext.getResources());

        mShelfIcons.setInNotificationIconShelf(true);
        if (!mShowNotificationShelf) {
            setVisibility(GONE);
@@ -203,6 +215,10 @@ public class NotificationShelf extends ActivatableNotificationView implements

            final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight();
            viewState.yTranslation = stackEnd - viewState.height;

            final int shortestWidth = mShelfIcons.calculateWidthFor(MAX_ICONS_ON_LOCKSCREEN);
            final float fraction = Interpolators.STANDARD.getInterpolation(mFractionToShade);
            updateStateWidth(viewState, fraction, shortestWidth);
        } else {
            viewState.hidden = true;
            viewState.location = ExpandableViewState.LOCATION_GONE;
@@ -210,6 +226,77 @@ public class NotificationShelf extends ActivatableNotificationView implements
        }
    }

    /**
     * @param shelfState View state for NotificationShelf
     * @param fraction Fraction of lockscreen to shade transition
     * @param shortestWidth Shortest width to use for lockscreen shelf
     */
    @VisibleForTesting
    public void updateStateWidth(ShelfState shelfState, float fraction, int shortestWidth) {
        shelfState.actualWidth = !mUseSplitShade && mAmbientState.isOnKeyguard()
                ? (int) MathUtils.lerp(shortestWidth, getWidth(), fraction)
                : getWidth();
    }

    /**
     * @param fractionToShade Fraction of lockscreen to shade transition
     */
    public void setFractionToShade(float fractionToShade) {
        mFractionToShade = fractionToShade;
    }

    /**
     * @return Actual width of shelf, accounting for possible ongoing width animation
     */
    public int getActualWidth() {
        return mActualWidth > -1 ? mActualWidth : getWidth();
    }

    /**
     * @param localX Click x from left of screen
     * @param slop Margin of error within which we count x for valid click
     * @param left Left of shelf, from left of screen
     * @param right Right of shelf, from left of screen
     * @return Whether click x was in view
     */
    @VisibleForTesting
    public boolean isXInView(float localX, float slop, float left, float right) {
        return (left - slop) <= localX && localX < (right + slop);
    }

    /**
     * @param localY Click y from top of shelf
     * @param slop Margin of error within which we count y for valid click
     * @param top Top of shelf
     * @param bottom Height of shelf
     * @return Whether click y was in view
     */
    @VisibleForTesting
    public boolean isYInView(float localY, float slop, float top, float bottom) {
        return (top - slop) <= localY && localY < (bottom + slop);
    }

    /**
     * @param localX Click x
     * @param localY Click y
     * @param slop Margin of error for valid click
     * @return Whether this click was on the visible (non-clipped) part of the shelf
     */
    @Override
    public boolean pointInView(float localX, float localY, float slop) {
        final float containerWidth = getWidth();
        final float shelfWidth = getActualWidth();

        final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0;
        final float right = isLayoutRtl() ? containerWidth : shelfWidth;

        final float top = mClipTopAmount;
        final float bottom = getActualHeight();

        return isXInView(localX, slop, left, right)
                && isYInView(localY, slop, top, bottom);
    }

    /**
     * Update the shelf appearance based on the other notifications around it. This transforms
     * the icons from the notification area into the shelf.
@@ -732,11 +819,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
        // we always want to clip to our sides, such that nothing can draw outside of these bounds
        int height = getResources().getDisplayMetrics().heightPixels;
        mClipRect.set(0, -height, getWidth(), height);
        if (mShelfIcons != null) {
            mShelfIcons.setClipBounds(mClipRect);
        }
    }

    private void updateRelativeOffset() {
        if (mCollapsedIcons != null) {
            mCollapsedIcons.getLocationOnScreen(mTmp);
        }
        getLocationOnScreen(mTmp);
    }

@@ -831,9 +922,20 @@ public class NotificationShelf extends ActivatableNotificationView implements
        mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
    }

    private class ShelfState extends ExpandableViewState {
    public class ShelfState extends ExpandableViewState {
        private boolean hasItemsInStableShelf;
        private ExpandableView firstViewInShelf;
        public int actualWidth = -1;

        private void updateShelfWidth(View view) {
            if (actualWidth < 0) {
                return;
            }
            mActualWidth = actualWidth;
            ActivatableNotificationView anv = (ActivatableNotificationView) view;
            anv.getBackgroundNormal().setActualWidth(actualWidth);
            mShelfIcons.setActualLayoutWidth(actualWidth);
        }

        @Override
        public void applyToView(View view) {
@@ -846,19 +948,21 @@ public class NotificationShelf extends ActivatableNotificationView implements
            updateAppearance();
            setHasItemsInStableShelf(hasItemsInStableShelf);
            mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
            updateShelfWidth(view);
        }

        @Override
        public void animateTo(View child, AnimationProperties properties) {
        public void animateTo(View view, AnimationProperties properties) {
            if (!mShowNotificationShelf) {
                return;
            }

            super.animateTo(child, properties);
            super.animateTo(view, properties);
            setIndexOfFirstViewInShelf(firstViewInShelf);
            updateAppearance();
            setHasItemsInStableShelf(hasItemsInStableShelf);
            mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
            updateShelfWidth(view);
        }
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -162,6 +162,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        updateBackgroundTint();
    }

    /**
     * @return The background of this view.
     */
    public NotificationBackgroundView getBackgroundNormal() {
        return mBackgroundNormal;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
+42 −14
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.View;

import com.android.internal.util.ArrayUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;

/**
@@ -39,15 +40,17 @@ public class NotificationBackgroundView extends View {
    private final boolean mDontModifyCorners;
    private Drawable mBackground;
    private int mClipTopAmount;
    private int mActualHeight;
    private int mClipBottomAmount;
    private int mTintColor;
    private final float[] mCornerRadii = new float[8];
    private boolean mBottomIsRounded;
    private int mBackgroundTop;
    private boolean mBottomAmountClips = true;
    private int mActualHeight = -1;
    private int mActualWidth = -1;
    private boolean mExpandAnimationRunning;
    private float mActualWidth;
    private int mExpandAnimationWidth = -1;
    private int mExpandAnimationHeight = -1;
    private int mDrawableAlpha = 255;
    private boolean mIsPressedAllowed;

@@ -59,11 +62,12 @@ public class NotificationBackgroundView extends View {

    @Override
    protected void onDraw(Canvas canvas) {
        if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop
        if (mClipTopAmount + mClipBottomAmount < getActualHeight() - mBackgroundTop
                || mExpandAnimationRunning) {
            canvas.save();
            if (!mExpandAnimationRunning) {
                canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
                canvas.clipRect(0, mClipTopAmount, getWidth(),
                        getActualHeight() - mClipBottomAmount);
            }
            draw(canvas, mBackground);
            canvas.restore();
@@ -73,17 +77,23 @@ public class NotificationBackgroundView extends View {
    private void draw(Canvas canvas, Drawable drawable) {
        if (drawable != null) {
            int top = mBackgroundTop;
            int bottom = mActualHeight;
            int bottom = getActualHeight();
            if (mBottomIsRounded
                    && mBottomAmountClips
                    && !mExpandAnimationRunning) {
                bottom -= mClipBottomAmount;
            }
            int left = 0;
            int right = getWidth();
            final boolean isRtl = isLayoutRtl();
            final int width = getWidth();
            final int actualWidth = getActualWidth();

            int left = isRtl ? width - actualWidth : 0;
            int right = isRtl ? width : actualWidth;

            if (mExpandAnimationRunning) {
                left = (int) ((getWidth() - mActualWidth) / 2.0f);
                right = (int) (left + mActualWidth);
                // Horizontally center this background view inside of the container
                left = (int) ((width - actualWidth) / 2.0f);
                right = (int) (left + actualWidth);
            }
            drawable.setBounds(left, top, right, bottom);
            drawable.draw(canvas);
@@ -152,9 +162,27 @@ public class NotificationBackgroundView extends View {
        invalidate();
    }

    public int getActualHeight() {
    private int getActualHeight() {
        if (mExpandAnimationRunning && mExpandAnimationHeight > -1) {
            return mExpandAnimationHeight;
        } else if (mActualHeight > -1) {
            return mActualHeight;
        }
        return getHeight();
    }

    public void setActualWidth(int actualWidth) {
        mActualWidth = actualWidth;
    }

    private int getActualWidth() {
        if (mExpandAnimationRunning && mExpandAnimationWidth > -1) {
            return mExpandAnimationWidth;
        } else if (mActualWidth > -1) {
            return mActualWidth;
        }
        return getWidth();
    }

    public void setClipTopAmount(int clipTopAmount) {
        mClipTopAmount = clipTopAmount;
@@ -241,9 +269,9 @@ public class NotificationBackgroundView extends View {
    }

    /** Set the current expand animation size. */
    public void setExpandAnimationSize(int actualWidth, int actualHeight) {
        mActualHeight = actualHeight;
        mActualWidth = actualWidth;
    public void setExpandAnimationSize(int width, int height) {
        mExpandAnimationHeight = width;
        mExpandAnimationWidth = height;
        invalidate();
    }

+11 −0
Original line number Diff line number Diff line
@@ -5496,6 +5496,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
        requestChildrenUpdate();
    }

    /**
     * @param fraction Fraction of the lockscreen to shade transition. 0f for all other states.
     *                 Once the lockscreen to shade transition completes and the shade is 100% open
     *                 LockscreenShadeTransitionController resets fraction to 0
     *                 where it remains until the next lockscreen-to-shade transition.
     */
    public void setFractionToShade(float fraction) {
        mShelf.setFractionToShade(fraction);
        requestChildrenUpdate();
    }

    /**
     * Set a listener to when scrolling changes.
     */
Loading