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

Commit aa94a61c authored by Mady Mellor's avatar Mady Mellor Committed by Android (Google) Code Review
Browse files

Merge "Improve swipe to show notification menu gesture" into oc-dev

parents 039dcadc 5574425c
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ public class SwipeHelper implements Gefingerpoken {
    public static final int X = 0;
    public static final int Y = 1;

    private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
    private float SWIPE_ESCAPE_VELOCITY = 500f; // dp/sec
    private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
    private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
    private int MAX_DISMISS_VELOCITY = 4000; // dp/sec
@@ -59,6 +59,9 @@ public class SwipeHelper implements Gefingerpoken {

    static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width
                                              // beyond which swipe progress->0
    public static final float SWIPED_FAR_ENOUGH_SIZE_FRACTION = 0.6f;
    static final float MAX_SCROLL_SIZE_FRACTION = 0.3f;

    private float mMinSwipeProgress = 0f;
    private float mMaxSwipeProgress = 1f;

@@ -363,9 +366,8 @@ public class SwipeHelper implements Gefingerpoken {
        // if the language is rtl we prefer swiping to the left
        boolean animateLeftForRtl = velocity == 0 && (getTranslation(animView) == 0 || isDismissAll)
                && isLayoutRtl;
        boolean animateLeft = velocity < 0
                || (velocity == 0 && getTranslation(animView) < 0 && !isDismissAll);

        boolean animateLeft = (Math.abs(velocity) > getEscapeVelocity() && velocity < 0) ||
                (getTranslation(animView) < 0 && !isDismissAll);
        if (animateLeft || animateLeftForRtl || animateUpForMenu) {
            newPos = -getSize(animView);
        } else {
@@ -584,7 +586,7 @@ public class SwipeHelper implements Gefingerpoken {
                    // maxScrollDistance
                    if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
                        float size = getSize(mCurrView);
                        float maxScrollDistance = 0.25f * size;
                        float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
                        if (absDelta >= size) {
                            delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
                        } else {
@@ -646,7 +648,8 @@ public class SwipeHelper implements Gefingerpoken {

    protected boolean swipedFarEnough() {
        float translation = getTranslation(mCurrView);
        return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
        return DISMISS_IF_SWIPED_FAR_ENOUGH
                && Math.abs(translation) > SWIPED_FAR_ENOUGH_SIZE_FRACTION * getSize(mCurrView);
    }

    public boolean isDismissGesture(MotionEvent ev) {
+70 −37
Original line number Diff line number Diff line
@@ -16,13 +16,13 @@

package com.android.systemui.statusbar;

import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;

import java.util.ArrayList;

import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.NotificationGuts.GutsContent;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -46,10 +46,21 @@ import android.widget.FrameLayout.LayoutParams;

public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener {

    private static final boolean DEBUG = false;
    private static final String TAG = "swipe";

    private static final int ICON_ALPHA_ANIM_DURATION = 200;
    private static final long SHOW_MENU_DELAY = 60;
    private static final long SWIPE_MENU_TIMING = 200;

    // Notification must be swiped at least this fraction of a single menu item to show menu
    private static final float SWIPED_FAR_ENOUGH_MENU_FRACTION = 0.25f;
    private static final float SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION = 0.15f;

    // When the menu is displayed, the notification must be swiped within this fraction of a single
    // menu item to snap back to menu (else it will cover the menu or it'll be dismissed)
    private static final float SWIPED_BACK_ENOUGH_TO_COVER_FRACTION = 0.2f;

    private ExpandableNotificationRow mParent;

    private Context mContext;
@@ -78,6 +89,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
    private int mIconPadding;

    private float mAlpha = 0f;
    private float mPrevX;

    private CheckForDrag mCheckForDrag;
    private Handler mHandler;
@@ -203,14 +215,14 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
                }
                mHandler.removeCallbacks(mCheckForDrag);
                mCheckForDrag = null;
                mPrevX = ev.getRawX();
                break;

            case MotionEvent.ACTION_MOVE:
                mSnapping = false;
                // If the menu is visible and the movement is towards it it's not a location change.
                boolean locationChange = isTowardsMenu(mTranslation)
                        ? false : isMenuLocationChange();
                if (locationChange) {
                float diffX = ev.getRawX() - mPrevX;
                mPrevX = ev.getRawX();
                if (!isTowardsMenu(diffX) && isMenuLocationChange()) {
                    // Don't consider it "snapped" if location has changed.
                    mMenuSnappedTo = false;

@@ -262,36 +274,53 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
        final double timeForGesture = ev.getEventTime() - ev.getDownTime();
        final boolean showMenuForSlowOnGoing = !mParent.canViewBeDismissed()
                && timeForGesture >= SWIPE_MENU_TIMING;

        final float targetLeft = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
        if (mMenuSnappedTo && isMenuVisible()) {
            if (mMenuSnappedOnLeft == mOnLeft) {
                boolean coveringMenu = Math.abs(mTranslation) <= getSpaceForMenu() * 0.6f;
                if (gestureTowardsMenu || coveringMenu) {
                    // Gesture is towards or covering the menu or a dismiss
                    snapBack(animView, 0);
                } else if (mSwipeHelper.isDismissGesture(ev)) {
                    dismiss(animView, velocity);
                } else {
                    // Didn't move enough to dismiss or cover, snap to the menu
                    showMenu(animView, targetLeft, velocity);
                }
            } else if ((!gestureFastEnough && swipedEnoughToShowMenu())
                    || (gestureTowardsMenu && !gestureFarEnough)) {
                // The menu has been snapped to previously, however, the menu is now on the
                // other side. If gesture is towards menu and not too far snap to the menu.
                showMenu(animView, targetLeft, velocity);
            } else if (mSwipeHelper.isDismissGesture(ev)) {
        final float menuSnapTarget = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();

        if (DEBUG) {
            Log.d(TAG, "mTranslation= " + mTranslation
                    + " mAlpha= " + mAlpha
                    + " velocity= " + velocity
                    + " mMenuSnappedTo= " + mMenuSnappedTo
                    + " mMenuSnappedOnLeft= " + mMenuSnappedOnLeft
                    + " mOnLeft= " + mOnLeft
                    + " minDismissVel= " + mSwipeHelper.getMinDismissVelocity()
                    + " isDismissGesture= " + mSwipeHelper.isDismissGesture(ev)
                    + " gestureTowardsMenu= " + gestureTowardsMenu
                    + " gestureFastEnough= " + gestureFastEnough
                    + " gestureFarEnough= " + gestureFarEnough);
        }

        if (mMenuSnappedTo && isMenuVisible() && mMenuSnappedOnLeft == mOnLeft) {
            // Menu was snapped to previously and we're on the same side, figure out if
            // we should stick to the menu, snap back into place, or dismiss
            final float maximumSwipeDistance = mHorizSpaceForIcon
                    * SWIPED_BACK_ENOUGH_TO_COVER_FRACTION;
            final float targetLeft = getSpaceForMenu() - maximumSwipeDistance;
            final float targetRight = mParent.getWidth() * SWIPED_FAR_ENOUGH_SIZE_FRACTION;
            boolean withinSnapMenuThreshold = mOnLeft
                    ? mTranslation > targetLeft && mTranslation < targetRight
                    : mTranslation < -targetLeft && mTranslation > -targetRight;
            boolean shouldSnapTo = mOnLeft ? mTranslation < targetLeft : mTranslation > -targetLeft;
            if (DEBUG) {
                Log.d(TAG, "   withinSnapMenuThreshold= " + withinSnapMenuThreshold
                        + "   shouldSnapTo= " + shouldSnapTo
                        + "   targetLeft= " + targetLeft
                        + "   targetRight= " + targetRight);
            }
            if (withinSnapMenuThreshold && !mSwipeHelper.isDismissGesture(ev)) {
                // Haven't moved enough to unsnap from the menu
                showMenu(animView, menuSnapTarget, velocity);
            } else if (mSwipeHelper.isDismissGesture(ev) && !shouldSnapTo) {
                // Only dismiss if we're not moving towards the menu
                dismiss(animView, velocity);
            } else {
                snapBack(animView, velocity);
            }
        } else if (((!gestureFastEnough || showMenuForSlowOnGoing)
                && swipedEnoughToShowMenu())
                || gestureTowardsMenu) {
        } else if ((swipedEnoughToShowMenu() && (!gestureFastEnough || showMenuForSlowOnGoing))
                || (gestureTowardsMenu && !mSwipeHelper.isDismissGesture(ev))) {
            // Menu has not been snapped to previously and this is menu revealing gesture
            showMenu(animView, targetLeft, velocity);
        } else if (mSwipeHelper.isDismissGesture(ev)) {
            showMenu(animView, menuSnapTarget, velocity);
        } else if (mSwipeHelper.isDismissGesture(ev) && !gestureTowardsMenu) {
            dismiss(animView, velocity);
        } else {
            snapBack(animView, velocity);
@@ -326,14 +355,18 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
        mSwipeHelper.dismiss(animView, velocity);
    }

    /**
     * @return whether the notification has been translated enough to show the menu and not enough
     *         to be dismissed.
     */
    private boolean swipedEnoughToShowMenu() {
        // If the notification can't be dismissed then how far it can move is
        // restricted -- reduce the distance it needs to move in this case.
        final float multiplier = mParent.canViewBeDismissed() ? 0.4f : 0.2f;
        final float snapBackThreshold = getSpaceForMenu() * multiplier;
        return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible() && (mOnLeft
                ? mTranslation > snapBackThreshold
                : mTranslation < -snapBackThreshold);
        final float multiplier = mParent.canViewBeDismissed()
                ? SWIPED_FAR_ENOUGH_MENU_FRACTION
                : SWIPED_FAR_ENOUGH_MENU_UNCLEARABLE_FRACTION;
        final float minimumSwipeDistance = mHorizSpaceForIcon * multiplier;
        return !mSwipeHelper.swipedFarEnough(0, 0) && isMenuVisible()
                && (mOnLeft ? mTranslation > minimumSwipeDistance
                        : mTranslation < -minimumSwipeDistance);
    }

    /**