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

Commit cdc4baaf authored by Lyn Han's avatar Lyn Han
Browse files

Round adjacent corners when swiping notification

Unround corners instantly when notification starts to snap back,
which feels more responsive.

Fix bug where fast consecutive swipes are ignored because
we did not set mTouchedView to the latest MotionEvent's view.

Bug: 171817112
Test: swiped sandwiched notification
     => rounds bottom corners of notification before
     => rounds top corners of notification after
        (in the same section; other sections not affected)
Test: swipe multiple notifications quickly
     => no jank

Change-Id: I1a808dd92f9e46df4767681d861ea73530d732a8
parent a4cd16ba
Loading
Loading
Loading
Loading
+5 −11
Original line number Diff line number Diff line
@@ -367,7 +367,7 @@ public class SwipeHelper implements Gefingerpoken {
    }

    /**
     * @param view The view to be dismissed
     * @param animView The view to be dismissed
     * @param velocity The desired pixels/second speed at which the view should move
     * @param endAction The action to perform at the end
     * @param delay The delay after which we should start
@@ -477,12 +477,8 @@ public class SwipeHelper implements Gefingerpoken {

    public void snapChild(final View animView, final float targetLeft, float velocity) {
        final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
        AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
            }
        };
        AnimatorUpdateListener updateListener = animation -> onTranslationUpdate(animView,
                (float) animation.getAnimatedValue(), canBeDismissed);

        Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
        if (anim == null) {
@@ -501,8 +497,6 @@ public class SwipeHelper implements Gefingerpoken {
                mSnappingChild = false;
                if (!wasCancelled) {
                    updateSwipeProgressFromOffset(animView, canBeDismissed);
                    onChildSnappedBack(animView, targetLeft);
                    mCallback.onChildSnappedBack(animView, targetLeft);
                    resetSwipeState();
                }
            }
@@ -513,6 +507,7 @@ public class SwipeHelper implements Gefingerpoken {
        mFlingAnimationUtils.apply(anim, getTranslation(animView), targetLeft, velocity,
                maxDistance);
        anim.start();
        mCallback.onChildSnappedBack(animView, targetLeft);
    }

    /**
@@ -594,13 +589,12 @@ public class SwipeHelper implements Gefingerpoken {

        if (!mIsSwiping && !mMenuRowIntercepting) {
            if (mCallback.getChildAtPosition(ev) != null) {

                // We are dragging directly over a card, make sure that we also catch the gesture
                // even if nobody else wants the touch event.
                mTouchedView = mCallback.getChildAtPosition(ev);
                onInterceptTouchEvent(ev);
                return true;
            } else {

                // We are not doing anything, make sure the long press callback
                // is not still ticking like a bomb waiting to go off.
                cancelLongPress();
+0 −9
Original line number Diff line number Diff line
@@ -69,7 +69,6 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
    private float mContentTranslation;
    protected boolean mLastInSection;
    protected boolean mFirstInSection;
    boolean mIsBeingSwiped;

    public ExpandableView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -174,14 +173,6 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
        return false;
    }

    public void setIsBeingSwiped(boolean swiped) {
        mIsBeingSwiped = swiped;
    }

    public boolean isBeingSwiped() {
        return mIsBeingSwiped;
    }

    public boolean isHeadsUpAnimatingAway() {
        return false;
    }
+62 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.stack;

import android.content.res.Resources;
import android.util.MathUtils;
import android.view.View;

import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
@@ -47,6 +48,10 @@ public class NotificationRoundnessManager {
    private ExpandableNotificationRow mTrackedHeadsUp;
    private float mAppearFraction;

    private ExpandableView mSwipedView = null;
    private ExpandableView mViewBeforeSwipedView = null;
    private ExpandableView mViewAfterSwipedView = null;

    @Inject
    NotificationRoundnessManager(
            KeyguardBypassController keyguardBypassController,
@@ -68,6 +73,11 @@ public class NotificationRoundnessManager {

    boolean updateViewWithoutCallback(ExpandableView view,
            boolean animate) {
        if (view == null
                || view == mViewBeforeSwipedView
                || view == mViewAfterSwipedView) {
            return false;
        }
        float topRoundness = getRoundness(view, true /* top */);
        float bottomRoundness = getRoundness(view, false /* top */);
        boolean topChanged = view.setTopRoundness(topRoundness, animate);
@@ -105,9 +115,60 @@ public class NotificationRoundnessManager {
        return false;
    }

    void setViewsAffectedBySwipe(
            ExpandableView viewBefore,
            ExpandableView viewSwiped,
            ExpandableView viewAfter,
            boolean cornerAnimationsEnabled) {
        if (!cornerAnimationsEnabled) {
            return;
        }
        final boolean animate = true;

        ExpandableView oldViewBefore = mViewBeforeSwipedView;
        mViewBeforeSwipedView = viewBefore;
        if (oldViewBefore != null) {
            final float bottomRoundness = getRoundness(oldViewBefore, false /* top */);
            oldViewBefore.setBottomRoundness(bottomRoundness,  animate);
        }
        if (viewBefore != null) {
            viewBefore.setBottomRoundness(1f, animate);
        }

        ExpandableView oldSwipedview = mSwipedView;
        mSwipedView = viewSwiped;
        if (oldSwipedview != null) {
            final float bottomRoundness = getRoundness(oldSwipedview, false /* top */);
            final float topRoundness = getRoundness(oldSwipedview, true /* top */);
            oldSwipedview.setTopRoundness(topRoundness, animate);
            oldSwipedview.setBottomRoundness(bottomRoundness, animate);
        }
        if (viewSwiped != null) {
            viewSwiped.setTopRoundness(1f, animate);
            viewSwiped.setBottomRoundness(1f, animate);
        }

        ExpandableView oldViewAfter = mViewAfterSwipedView;
        mViewAfterSwipedView = viewAfter;
        if (oldViewAfter != null) {
            final float topRoundness = getRoundness(oldViewAfter, true /* top */);
            oldViewAfter.setTopRoundness(topRoundness, animate);
        }
        if (viewAfter != null) {
            viewAfter.setTopRoundness(1f, animate);
        }
    }

    private float getRoundness(ExpandableView view, boolean top) {
        if (view == null) {
            return 0f;
        }
        if (view == mViewBeforeSwipedView
                || view == mSwipedView
                || view == mViewAfterSwipedView) {
            return 1f;
        }
        if ((view.isPinned()
                || view.isBeingSwiped()
                || (view.isHeadsUpAnimatingAway()) && !mExpanded)) {
            return 1.0f;
        }
+36 −19
Original line number Diff line number Diff line
@@ -1025,8 +1025,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
            boolean clip = clipStart > start && clipStart < end
                    || clipEnd >= start && clipEnd <= end;
            clip &= !(first && mScrollAdapter.isScrolledToTop());
            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
                    : ExpandableView.NO_ROUNDNESS);
            child.setDistanceToTopRoundness(ExpandableView.NO_ROUNDNESS);
            first = false;
        }
    }
@@ -2292,9 +2291,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
            ExpandableView child = (ExpandableView) getChildAt(i);
            if (child.getVisibility() != View.GONE
                    && !(child instanceof StackScrollerDecorView)
                    && child != mShelf
                    && (mSwipeHelper.getSwipedView() != child
                        || !child.getResources().getBoolean(R.bool.flag_notif_updates))) {
                    && child != mShelf) {
                children.add(child);
            }
        }
@@ -4993,28 +4990,48 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
        mSwipedOutViews.add(v);
    }

    void onSwipeBegin(View v) {
        if (v instanceof ExpandableView) {
            ExpandableView ev = (ExpandableView) v;
            ev.setIsBeingSwiped(true);
            mController.getNoticationRoundessManager()
                    .updateViewWithoutCallback(ev, true /* animate */);
    void onSwipeBegin(View viewSwiped) {
        if (!(viewSwiped instanceof ExpandableNotificationRow)) {
            return;
        }
        requestDisallowInterceptTouchEvent(true);
        final int indexOfSwipedView = indexOfChild(viewSwiped);
        if (indexOfSwipedView < 0) {
            return;
        }
        mSectionsManager.updateFirstAndLastViewsForAllSections(
                mSections, getChildrenWithBackground());
        View viewBefore = null;
        if (indexOfSwipedView > 0) {
            viewBefore = getChildAt(indexOfSwipedView - 1);
            if (mSectionsManager.beginsSection(viewSwiped, viewBefore)) {
                viewBefore = null;
            }
        }
        View viewAfter = null;
        if (indexOfSwipedView < getChildCount()) {
            viewAfter = getChildAt(indexOfSwipedView + 1);
            if (mSectionsManager.beginsSection(viewAfter, viewSwiped)) {
                viewAfter = null;
            }
        }
        mController.getNoticationRoundessManager()
                .setViewsAffectedBySwipe((ExpandableView) viewBefore,
                        (ExpandableView) viewSwiped,
                        (ExpandableView) viewAfter,
                        getResources().getBoolean(R.bool.flag_notif_updates));

        updateFirstAndLastBackgroundViews();
        requestDisallowInterceptTouchEvent(true);
        updateContinuousShadowDrawing();
        updateContinuousBackgroundDrawing();
        requestChildrenUpdate();
    }

    void onSwipeEnd(View v) {
        if (v instanceof ExpandableView) {
            ExpandableView ev = (ExpandableView) v;
            ev.setIsBeingSwiped(false);
            mController.getNoticationRoundessManager()
                    .updateViewWithoutCallback(ev, true /* animate */);
        }
    void onSwipeEnd() {
        updateFirstAndLastBackgroundViews();
        mController.getNoticationRoundessManager()
                .setViewsAffectedBySwipe(null, null, null,
                        getResources().getBoolean(R.bool.flag_notif_updates));
    }

    void setTopHeadsUpEntry(NotificationEntry topEntry) {
+2 −2
Original line number Diff line number Diff line
@@ -399,7 +399,7 @@ public class NotificationStackScrollLayoutController {
                    if (mView.getDismissAllInProgress()) {
                        return;
                    }
                    mView.onSwipeEnd(view);
                    mView.onSwipeEnd();
                    if (view instanceof ExpandableNotificationRow) {
                        ExpandableNotificationRow row = (ExpandableNotificationRow) view;
                        if (row.isHeadsUp()) {
@@ -459,7 +459,7 @@ public class NotificationStackScrollLayoutController {

                @Override
                public void onChildSnappedBack(View animView, float targetLeft) {
                    mView.onSwipeEnd(animView);
                    mView.onSwipeEnd();
                    if (animView instanceof ExpandableNotificationRow) {
                        ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
                        if (row.isPinned() && !canChildBeDismissed(row)