Loading packages/SystemUI/src/com/android/systemui/SwipeHelper.java +9 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +70 −37 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } /** Loading Loading
packages/SystemUI/src/com/android/systemui/SwipeHelper.java +9 −6 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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; Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +70 −37 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); } /** Loading