OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.contextualsearch; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.graphics.PointF; |
| 9 import android.view.GestureDetector; |
| 10 import android.view.GestureDetector.SimpleOnGestureListener; |
| 11 import android.view.MotionEvent; |
| 12 |
| 13 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeEvent
Filter.ScrollDirection; |
| 14 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandl
er; |
| 15 |
| 16 /** |
| 17 * TODO(pedrosimonetti): Confirm with dtrainor@ the proper location for this fil
e. |
| 18 * |
| 19 * Recognizes directional swipe gestures using supplied {@link MotionEvent}s. |
| 20 * The {@EdgeSwipeHandler} callbacks will notify users when a particular gesture |
| 21 * has occurred, if the handler supports the particular direction of the swipe. |
| 22 * |
| 23 * To use this class: |
| 24 * <ul> |
| 25 * <li>Create an instance of the {@code SwipeRecognizer} for your View |
| 26 * <li>In the View#onTouchEvent(MotionEvent) method ensure you call |
| 27 * {@link #onTouchEvent(MotionEvent)}. The methods defined in your call
back |
| 28 * will be executed when the gestures occur. |
| 29 * <li>Before trying to recognize the gesture, the class will call |
| 30 * {@link #shouldRecognizeSwipe(MotionEvent, MotionEvent)}, which allow |
| 31 * ignoring swipe recognition based on the MotionEvents. |
| 32 * <li>Once a swipe gesture is detected, the class will check if the the direct
ion |
| 33 * is supported by calling {@link EdgeSwipeHandler#isSwipeEnabled(Scrol
lDirection)}. |
| 34 * </ul> |
| 35 |
| 36 * Internally, this class uses a {@link GestureDetector} to recognize swipe gest
ures. |
| 37 * For convenience, this class also extends {@link SimpleOnGestureListener} whic
h |
| 38 * is passed to the {@GestureDetector}. This means that this class can also be |
| 39 * used to detect simple gestures defined in {@link GestureDetector}. |
| 40 */ |
| 41 public class SwipeRecognizer extends SimpleOnGestureListener { |
| 42 |
| 43 /** |
| 44 * The threshold for a vertical swipe gesture, in dps. |
| 45 */ |
| 46 private static final float SWIPE_VERTICAL_DRAG_THRESHOLD_DP = 5.f; |
| 47 |
| 48 /** |
| 49 * The threshold for a horizontal swipe gesture, in dps. |
| 50 */ |
| 51 private static final float SWIPE_HORIZONTAL_DRAG_THRESHOLD_DP = 10.f; |
| 52 |
| 53 /** |
| 54 * The {@link EdgeSwipeHandler} that will respond to recognized gestures. |
| 55 */ |
| 56 private EdgeSwipeHandler mSwipeHandler; |
| 57 |
| 58 /** |
| 59 * The direction of the swipe gesture. |
| 60 * TODO(pedrosimonetti): Consider renaming ScrollDirection to SwipeDirection
. |
| 61 * Also consider renaming EdgeSwipeHandler to SwipeHandler or DirectionalSwi
peHandler. |
| 62 * Finally, consider moving the ScrollDirection/SwipeDirection enum to this
class. |
| 63 */ |
| 64 private ScrollDirection mSwipeDirection = ScrollDirection.UNKNOWN; |
| 65 |
| 66 /** |
| 67 * The point that originated the swipe gesture. |
| 68 */ |
| 69 private final PointF mMotionStartPoint = new PointF(); |
| 70 |
| 71 /** |
| 72 * The dps per pixel ratio. |
| 73 */ |
| 74 private final float mPxToDp; |
| 75 |
| 76 /** |
| 77 * The internal {@GestureDetector} used to recognize swipe gestures. |
| 78 */ |
| 79 private final GestureDetector mGestureDetector; |
| 80 |
| 81 /** |
| 82 * @param context The current Android {@link Context}. |
| 83 */ |
| 84 public SwipeRecognizer(Context context) { |
| 85 mPxToDp = 1.f / context.getResources().getDisplayMetrics().density; |
| 86 mGestureDetector = new GestureDetector(context, this); |
| 87 } |
| 88 |
| 89 /** |
| 90 * Sets the {@link EdgeSwipeHandler} that will respond to recognized gesture
s. |
| 91 * @param handler The {@link EdgeSwipeHandler}. |
| 92 */ |
| 93 public void setSwipeHandler(EdgeSwipeHandler handler) { |
| 94 mSwipeHandler = handler; |
| 95 } |
| 96 |
| 97 /** |
| 98 * Analyzes the given motion event by feeding it to a {@GestureDetector}. De
pending on the |
| 99 * results from the onScroll() and onFling() methods, it triggers the approp
riate callbacks |
| 100 * on the {@link EdgeSwipeHandler} supplied. |
| 101 * |
| 102 * @param event The {@link MotionEvent}. |
| 103 * @return Whether the event has been consumed. |
| 104 */ |
| 105 public boolean onTouchEvent(MotionEvent event) { |
| 106 boolean consumed = mGestureDetector.onTouchEvent(event); |
| 107 |
| 108 if (mSwipeHandler != null) { |
| 109 final int action = event.getAction(); |
| 110 if ((action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION
_CANCEL) |
| 111 && mSwipeDirection != ScrollDirection.UNKNOWN) { |
| 112 mSwipeHandler.swipeFinished(); |
| 113 mSwipeDirection = ScrollDirection.UNKNOWN; |
| 114 consumed = true; |
| 115 } |
| 116 } |
| 117 |
| 118 return consumed; |
| 119 } |
| 120 |
| 121 /** |
| 122 * Checks whether the swipe gestures should be recognized. If this method re
turns false, |
| 123 * then the whole swipe recognition process will be ignored. By default this
method returns |
| 124 * true. If a more complex logic is needed, this method should be overridden
. |
| 125 * |
| 126 * @param e1 The first {@link MotionEvent}. |
| 127 * @param e2 The second {@link MotionEvent}. |
| 128 * @return Whether the swipe gestures should be recognized |
| 129 */ |
| 130 public boolean shouldRecognizeSwipe(MotionEvent e1, MotionEvent e2) { |
| 131 return true; |
| 132 } |
| 133 |
| 134 // =========================================================================
=================== |
| 135 // Swipe Recognition Helpers |
| 136 // =========================================================================
=================== |
| 137 |
| 138 @Override |
| 139 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, flo
at distanceY) { |
| 140 if (mSwipeHandler == null || e1 == null || e2 == null) return false; |
| 141 |
| 142 final float x = e2.getRawX() * mPxToDp; |
| 143 final float y = e2.getRawY() * mPxToDp; |
| 144 |
| 145 if (mSwipeDirection == ScrollDirection.UNKNOWN && shouldRecognizeSwipe(e
1, e2)) { |
| 146 float tx = (e2.getRawX() - e1.getRawX()) * mPxToDp; |
| 147 float ty = (e2.getRawY() - e1.getRawY()) * mPxToDp; |
| 148 |
| 149 ScrollDirection direction = ScrollDirection.UNKNOWN; |
| 150 |
| 151 if (Math.abs(tx) > SWIPE_HORIZONTAL_DRAG_THRESHOLD_DP) { |
| 152 direction = tx > 0.f ? ScrollDirection.RIGHT : ScrollDirection.L
EFT; |
| 153 } else if (Math.abs(ty) > SWIPE_VERTICAL_DRAG_THRESHOLD_DP) { |
| 154 direction = ty > 0.f ? ScrollDirection.DOWN : ScrollDirection.UP
; |
| 155 } |
| 156 |
| 157 if (direction != ScrollDirection.UNKNOWN && mSwipeHandler.isSwipeEna
bled(direction)) { |
| 158 mSwipeDirection = direction; |
| 159 mSwipeHandler.swipeStarted(direction, x, y); |
| 160 mMotionStartPoint.set(e2.getRawX(), e2.getRawY()); |
| 161 } |
| 162 } |
| 163 |
| 164 if (mSwipeDirection != ScrollDirection.UNKNOWN) { |
| 165 final float tx = (e2.getRawX() - mMotionStartPoint.x) * mPxToDp; |
| 166 final float ty = (e2.getRawY() - mMotionStartPoint.y) * mPxToDp; |
| 167 final float dx = -distanceX * mPxToDp; |
| 168 final float dy = -distanceY * mPxToDp; |
| 169 |
| 170 mSwipeHandler.swipeUpdated(x, y, dx, dy, tx, ty); |
| 171 return true; |
| 172 } |
| 173 |
| 174 return false; |
| 175 } |
| 176 |
| 177 @Override |
| 178 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, floa
t velocityY) { |
| 179 if (mSwipeHandler == null) return false; |
| 180 |
| 181 if (mSwipeDirection != ScrollDirection.UNKNOWN) { |
| 182 final float x = e2.getRawX() * mPxToDp; |
| 183 final float y = e2.getRawY() * mPxToDp; |
| 184 final float tx = (e2.getRawX() - mMotionStartPoint.x) * mPxToDp; |
| 185 final float ty = (e2.getRawY() - mMotionStartPoint.y) * mPxToDp; |
| 186 final float vx = velocityX * mPxToDp; |
| 187 final float vy = velocityY * mPxToDp; |
| 188 |
| 189 mSwipeHandler.swipeFlingOccurred(x, y, tx, ty, vx, vy); |
| 190 return true; |
| 191 } |
| 192 |
| 193 return false; |
| 194 } |
| 195 } |
OLD | NEW |