package com.android.systemui.shared.system;
import android.annotation.IntDef;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import sun.misc.Resource;
+
public class NavigationBarCompat {
+ /**
+ * Touch slopes and thresholds for quick step operations. Drag slop is the point where the
+ * home button press/long press over are ignored and will start to drag when exceeded and the
+ * touch slop is when the respected operation will occur when exceeded. Touch slop must be
+ * larger than the drag slop.
+ */
+ public static final int QUICK_STEP_DRAG_SLOP_PX = convertDpToPixel(10);
+ public static final int QUICK_SCRUB_DRAG_SLOP_PX = convertDpToPixel(20);
+ public static final int QUICK_STEP_TOUCH_SLOP_PX = convertDpToPixel(40);
+ public static final int QUICK_SCRUB_TOUCH_SLOP_PX = convertDpToPixel(35);
+
@Retention(RetentionPolicy.SOURCE)
@IntDef({HIT_TARGET_NONE, HIT_TARGET_BACK, HIT_TARGET_HOME, HIT_TARGET_OVERVIEW})
public @interface HitTarget{}
* Interaction type: whether the gesture to swipe up from the navigation bar will trigger
* launcher to show overview
*/
-
public static final int FLAG_DISABLE_SWIPE_UP = 0x1;
/**
* Interaction type: enable quick scrub interaction on the home button
* Interaction type: show/hide the back button while this service is connected to launcher
*/
public static final int FLAG_HIDE_BACK_BUTTON = 0x8;
+
+ private static int convertDpToPixel(float dp){
+ return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
+ }
}
import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
import static com.android.systemui.OverviewProxyService.TAG_OPS;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
+import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_SCRUB_DRAG_SLOP_PX;
+import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_SCRUB_TOUCH_SLOP_PX;
+import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX;
+import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_TOUCH_SLOP_PX;
/**
* Class to detect gestures on the navigation bar and implement quick scrub.
private float mTranslation;
private int mTouchDownX;
private int mTouchDownY;
+ private boolean mDragScrubActive;
private boolean mDragPositive;
private boolean mIsVertical;
private boolean mIsRTL;
private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
private final Rect mTrackRect = new Rect();
private final Paint mTrackPaint = new Paint();
- private final int mScrollTouchSlop;
private final OverviewProxyService mOverviewEventSender;
private final int mTrackThickness;
private final int mTrackPadding;
@Override
public void onAnimationEnd(Animator animation) {
mQuickScrubActive = false;
+ mDragScrubActive = false;
mTranslation = 0;
mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
mHomeButtonView = null;
public QuickStepController(Context context) {
mContext = context;
- mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mOverviewEventSender = Dependency.get(OverviewProxyService.class);
mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
mTrackPadding = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_edge_padding);
final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
- int action = event.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
+ int action = event.getActionMasked();
+ switch (action) {
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
int y = (int) event.getY();
int xDiff = Math.abs(x - mTouchDownX);
int yDiff = Math.abs(y - mTouchDownY);
- boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
- boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
- boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
+
+ boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop, exceededScrubDragSlop;
int pos, touchDown, offset, trackSize;
if (mIsVertical) {
- exceededTouchSlop = exceededTouchSlopY;
- exceededPerpendicularTouchSlop = exceededTouchSlopX;
+ exceededScrubTouchSlop = yDiff > QUICK_STEP_TOUCH_SLOP_PX && yDiff > xDiff;
+ exceededSwipeUpTouchSlop = xDiff > QUICK_STEP_DRAG_SLOP_PX && xDiff > yDiff;
+ exceededScrubDragSlop = yDiff > QUICK_SCRUB_DRAG_SLOP_PX && yDiff > xDiff;
pos = y;
touchDown = mTouchDownY;
offset = pos - mTrackRect.top;
trackSize = mTrackRect.height();
} else {
- exceededTouchSlop = exceededTouchSlopX;
- exceededPerpendicularTouchSlop = exceededTouchSlopY;
+ exceededScrubTouchSlop = xDiff > QUICK_STEP_TOUCH_SLOP_PX && xDiff > yDiff;
+ exceededSwipeUpTouchSlop = yDiff > QUICK_SCRUB_TOUCH_SLOP_PX && yDiff > xDiff;
+ exceededScrubDragSlop = xDiff > QUICK_SCRUB_DRAG_SLOP_PX && xDiff > yDiff;
pos = x;
touchDown = mTouchDownX;
offset = pos - mTrackRect.left;
}
// Decide to start quickstep if dragging away from the navigation bar, otherwise in
// the parallel direction, decide to start quickscrub. Only one may run.
- if (!mQuickScrubActive && exceededPerpendicularTouchSlop) {
+ if (!mQuickScrubActive && exceededSwipeUpTouchSlop) {
if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
startQuickStep(event);
}
offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
}
- // Control the button movement
- if (!mQuickScrubActive && exceededTouchSlop) {
- boolean allowDrag = !mDragPositive
- ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
- if (allowDrag) {
+ final boolean allowDrag = !mDragPositive
+ ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
+ if (allowDrag) {
+ // Passing the drag slop is for visual feedback and will not initiate anything
+ if (!mDragScrubActive && exceededScrubDragSlop) {
mDownOffset = offset;
+ mDragScrubActive = true;
+ }
+
+ // Passing the drag slop then touch slop will start quick step
+ if (!mQuickScrubActive && exceededScrubTouchSlop) {
homeButton.abortCurrentGesture();
startQuickScrub();
}
}
- if (mQuickScrubActive && (mDragPositive && offset >= 0
+
+ if ((mQuickScrubActive || mDragScrubActive) && (mDragPositive && offset >= 0
|| !mDragPositive && offset <= 0)) {
- float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
mTranslation = !mDragPositive
- ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
- : Utilities.clamp(offset - mDownOffset, 0, trackSize);
- try {
- mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
+ ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
+ : Utilities.clamp(offset - mDownOffset, 0, trackSize);
+ if (mQuickScrubActive) {
+ float scrubFraction =
+ Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
+ try {
+ mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
if (mIsVertical) {
mHomeButtonView.setTranslationY(mTranslation);
}
// Proxy motion events to launcher if not handled by quick scrub
- if (!mQuickScrubActive && mAllowGestureDetection) {
+ // Proxy motion events up/cancel that would be sent after long press on any nav button
+ if (!mQuickScrubActive && (mAllowGestureDetection || action == MotionEvent.ACTION_CANCEL
+ || action == MotionEvent.ACTION_UP)) {
proxyMotionEvents(event);
}
return mQuickScrubActive || mQuickStepStarted;
mOverviewEventSender.notifyQuickStepStarted();
mNavigationBarView.getHomeButton().abortCurrentGesture();
mHandler.removeCallbacksAndMessages(null);
+
+ if (mDragScrubActive) {
+ animateEnd();
+ }
}
private void startQuickScrub() {
- if (!mQuickScrubActive) {
+ if (!mQuickScrubActive && mDragScrubActive) {
mQuickScrubActive = true;
mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
}
private void endQuickScrub(boolean animate) {
- if (mQuickScrubActive) {
+ if (mQuickScrubActive || mDragScrubActive) {
animateEnd();
- try {
- mOverviewEventSender.getProxy().onQuickScrubEnd();
- if (DEBUG_OVERVIEW_PROXY) {
- Log.d(TAG_OPS, "Quick Scrub End");
+ if (mQuickScrubActive) {
+ try {
+ mOverviewEventSender.getProxy().onQuickScrubEnd();
+ if (DEBUG_OVERVIEW_PROXY) {
+ Log.d(TAG_OPS, "Quick Scrub End");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send end of quick scrub.", e);
}
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send end of quick scrub.", e);
}
}
if (mHomeButtonView != null && !animate) {