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

Commit b4809f27 authored by Mady Mellor's avatar Mady Mellor Committed by android-build-merger
Browse files

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

am: aa94a61c

Change-Id: I8221d18deed280c08d93739bcaf24bca0454b302
parents 2a711c3c aa94a61c
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);
    }

    /**