Merge "Improve swipe to show notification menu gesture" into oc-dev
am: aa94a61c56
Change-Id: I8221d18deed280c08d93739bcaf24bca0454b302
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 menuSnapTarget = mOnLeft ? getSpaceForMenu() : -getSpaceForMenu();
|
||||
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user