1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.view; 18 19import android.os.Build; 20import android.view.MotionEvent; 21 22/** 23 * Helper for accessing features in {@link MotionEvent} introduced 24 * after API level 4 in a backwards compatible fashion. 25 */ 26public class MotionEventCompat { 27 /** 28 * Interface for the full API. 29 */ 30 interface MotionEventVersionImpl { 31 public int findPointerIndex(MotionEvent event, int pointerId); 32 public int getPointerId(MotionEvent event, int pointerIndex); 33 public float getX(MotionEvent event, int pointerIndex); 34 public float getY(MotionEvent event, int pointerIndex); 35 public int getPointerCount(MotionEvent event); 36 public int getSource(MotionEvent event); 37 float getAxisValue(MotionEvent event, int axis); 38 float getAxisValue(MotionEvent event, int axis, int pointerIndex); 39 } 40 41 /** 42 * Interface implementation that doesn't use anything about v4 APIs. 43 */ 44 static class BaseMotionEventVersionImpl implements MotionEventVersionImpl { 45 @Override 46 public int findPointerIndex(MotionEvent event, int pointerId) { 47 if (pointerId == 0) { 48 // id 0 == index 0 and vice versa. 49 return 0; 50 } 51 return -1; 52 } 53 @Override 54 public int getPointerId(MotionEvent event, int pointerIndex) { 55 if (pointerIndex == 0) { 56 // index 0 == id 0 and vice versa. 57 return 0; 58 } 59 throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers"); 60 } 61 @Override 62 public float getX(MotionEvent event, int pointerIndex) { 63 if (pointerIndex == 0) { 64 return event.getX(); 65 } 66 throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers"); 67 } 68 @Override 69 public float getY(MotionEvent event, int pointerIndex) { 70 if (pointerIndex == 0) { 71 return event.getY(); 72 } 73 throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers"); 74 } 75 @Override 76 public int getPointerCount(MotionEvent event) { 77 return 1; 78 } 79 80 @Override 81 public int getSource(MotionEvent event) { 82 return InputDeviceCompat.SOURCE_UNKNOWN; 83 } 84 85 @Override 86 public float getAxisValue(MotionEvent event, int axis) { 87 return 0; 88 } 89 90 @Override 91 public float getAxisValue(MotionEvent event, int axis, int pointerIndex) { 92 return 0; 93 } 94 } 95 96 /** 97 * Interface implementation for devices with at least v5 APIs. 98 */ 99 static class EclairMotionEventVersionImpl extends BaseMotionEventVersionImpl { 100 @Override 101 public int findPointerIndex(MotionEvent event, int pointerId) { 102 return MotionEventCompatEclair.findPointerIndex(event, pointerId); 103 } 104 @Override 105 public int getPointerId(MotionEvent event, int pointerIndex) { 106 return MotionEventCompatEclair.getPointerId(event, pointerIndex); 107 } 108 @Override 109 public float getX(MotionEvent event, int pointerIndex) { 110 return MotionEventCompatEclair.getX(event, pointerIndex); 111 } 112 @Override 113 public float getY(MotionEvent event, int pointerIndex) { 114 return MotionEventCompatEclair.getY(event, pointerIndex); 115 } 116 @Override 117 public int getPointerCount(MotionEvent event) { 118 return MotionEventCompatEclair.getPointerCount(event); 119 } 120 } 121 122 /** 123 * Interface implementation for devices with at least v8 APIs. 124 */ 125 static class GingerbreadMotionEventVersionImpl extends EclairMotionEventVersionImpl { 126 @Override 127 public int getSource(MotionEvent event) { 128 return MotionEventCompatGingerbread.getSource(event); 129 } 130 } 131 132 /** 133 * Interface implementation for devices with at least v12 APIs. 134 */ 135 static class HoneycombMr1MotionEventVersionImpl extends GingerbreadMotionEventVersionImpl { 136 137 @Override 138 public float getAxisValue(MotionEvent event, int axis) { 139 return MotionEventCompatHoneycombMr1.getAxisValue(event, axis); 140 } 141 142 @Override 143 public float getAxisValue(MotionEvent event, int axis, int pointerIndex) { 144 return MotionEventCompatHoneycombMr1.getAxisValue(event, axis, pointerIndex); 145 } 146 } 147 148 /** 149 * Select the correct implementation to use for the current platform. 150 */ 151 static final MotionEventVersionImpl IMPL; 152 static { 153 if (Build.VERSION.SDK_INT >= 12) { 154 IMPL = new HoneycombMr1MotionEventVersionImpl(); 155 } else if (Build.VERSION.SDK_INT >= 9) { 156 IMPL = new GingerbreadMotionEventVersionImpl(); 157 } else if (Build.VERSION.SDK_INT >= 5) { 158 IMPL = new EclairMotionEventVersionImpl(); 159 } else { 160 IMPL = new BaseMotionEventVersionImpl(); 161 } 162 } 163 164 // ------------------------------------------------------------------- 165 166 /** 167 * Synonym for {@link MotionEvent#ACTION_MASK}. 168 */ 169 public static final int ACTION_MASK = 0xff; 170 171 /** 172 * Synonym for {@link MotionEvent#ACTION_POINTER_DOWN}. 173 */ 174 public static final int ACTION_POINTER_DOWN = 5; 175 176 /** 177 * Synonym for {@link MotionEvent#ACTION_POINTER_UP}. 178 */ 179 public static final int ACTION_POINTER_UP = 6; 180 181 /** 182 * Synonym for {@link MotionEvent#ACTION_HOVER_MOVE}. 183 */ 184 public static final int ACTION_HOVER_MOVE = 7; 185 186 /** 187 * Synonym for {@link MotionEvent#ACTION_SCROLL}. 188 */ 189 public static final int ACTION_SCROLL = 8; 190 191 /** 192 * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_MASK}. 193 */ 194 public static final int ACTION_POINTER_INDEX_MASK = 0xff00; 195 196 /** 197 * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_SHIFT}. 198 */ 199 public static final int ACTION_POINTER_INDEX_SHIFT = 8; 200 201 /** 202 * Synonym for {@link MotionEvent#ACTION_HOVER_ENTER}. 203 */ 204 public static final int ACTION_HOVER_ENTER = 9; 205 206 /** 207 * Synonym for {@link MotionEvent#ACTION_HOVER_EXIT}. 208 */ 209 public static final int ACTION_HOVER_EXIT = 10; 210 211 /** 212 * Synonym for {@link MotionEvent#AXIS_X}. 213 */ 214 public static final int AXIS_X = 0; 215 216 /** 217 * Synonym for {@link MotionEvent#AXIS_Y}. 218 */ 219 public static final int AXIS_Y = 1; 220 221 /** 222 * Synonym for {@link MotionEvent#AXIS_PRESSURE}. 223 */ 224 public static final int AXIS_PRESSURE = 2; 225 226 /** 227 * Synonym for {@link MotionEvent#AXIS_SIZE}. 228 */ 229 public static final int AXIS_SIZE = 3; 230 231 /** 232 * Synonym for {@link MotionEvent#AXIS_TOUCH_MAJOR}. 233 */ 234 public static final int AXIS_TOUCH_MAJOR = 4; 235 236 /** 237 * Synonym for {@link MotionEvent#AXIS_TOUCH_MINOR}. 238 */ 239 public static final int AXIS_TOUCH_MINOR = 5; 240 241 /** 242 * Synonym for {@link MotionEvent#AXIS_TOOL_MAJOR}. 243 */ 244 public static final int AXIS_TOOL_MAJOR = 6; 245 246 /** 247 * Synonym for {@link MotionEvent#AXIS_TOOL_MINOR}. 248 */ 249 public static final int AXIS_TOOL_MINOR = 7; 250 251 /** 252 * Synonym for {@link MotionEvent#AXIS_ORIENTATION}. 253 */ 254 public static final int AXIS_ORIENTATION = 8; 255 256 /** 257 * Synonym for {@link MotionEvent#AXIS_VSCROLL}. 258 */ 259 public static final int AXIS_VSCROLL = 9; 260 261 /** 262 * Synonym for {@link MotionEvent#AXIS_HSCROLL}. 263 */ 264 public static final int AXIS_HSCROLL = 10; 265 266 /** 267 * Synonym for {@link MotionEvent#AXIS_Z}. 268 */ 269 public static final int AXIS_Z = 11; 270 271 /** 272 * Synonym for {@link MotionEvent#AXIS_RX}. 273 */ 274 public static final int AXIS_RX = 12; 275 276 /** 277 * Synonym for {@link MotionEvent#AXIS_RY}. 278 */ 279 public static final int AXIS_RY = 13; 280 281 /** 282 * Synonym for {@link MotionEvent#AXIS_RZ}. 283 */ 284 public static final int AXIS_RZ = 14; 285 286 /** 287 * Synonym for {@link MotionEvent#AXIS_HAT_X}. 288 */ 289 public static final int AXIS_HAT_X = 15; 290 291 /** 292 * Synonym for {@link MotionEvent#AXIS_HAT_Y}. 293 */ 294 public static final int AXIS_HAT_Y = 16; 295 296 /** 297 * Synonym for {@link MotionEvent#AXIS_LTRIGGER}. 298 */ 299 public static final int AXIS_LTRIGGER = 17; 300 301 /** 302 * Synonym for {@link MotionEvent#AXIS_RTRIGGER}. 303 */ 304 public static final int AXIS_RTRIGGER = 18; 305 306 /** 307 * Synonym for {@link MotionEvent#AXIS_THROTTLE}. 308 */ 309 public static final int AXIS_THROTTLE = 19; 310 311 /** 312 * Synonym for {@link MotionEvent#AXIS_RUDDER}. 313 */ 314 public static final int AXIS_RUDDER = 20; 315 316 /** 317 * Synonym for {@link MotionEvent#AXIS_WHEEL}. 318 */ 319 public static final int AXIS_WHEEL = 21; 320 321 /** 322 * Synonym for {@link MotionEvent#AXIS_GAS}. 323 */ 324 public static final int AXIS_GAS = 22; 325 326 /** 327 * Synonym for {@link MotionEvent#AXIS_BRAKE}. 328 */ 329 public static final int AXIS_BRAKE = 23; 330 331 /** 332 * Synonym for {@link MotionEvent#AXIS_DISTANCE}. 333 */ 334 public static final int AXIS_DISTANCE = 24; 335 336 /** 337 * Synonym for {@link MotionEvent#AXIS_TILT}. 338 */ 339 public static final int AXIS_TILT = 25; 340 341 /** 342 * Synonym for {@link MotionEvent#AXIS_GENERIC_1}. 343 */ 344 public static final int AXIS_GENERIC_1 = 32; 345 346 /** 347 * Synonym for {@link MotionEvent#AXIS_GENERIC_2}. 348 */ 349 public static final int AXIS_GENERIC_2 = 33; 350 351 /** 352 * Synonym for {@link MotionEvent#AXIS_GENERIC_3}. 353 */ 354 public static final int AXIS_GENERIC_3 = 34; 355 356 /** 357 * Synonym for {@link MotionEvent#AXIS_GENERIC_4}. 358 */ 359 public static final int AXIS_GENERIC_4 = 35; 360 361 /** 362 * Synonym for {@link MotionEvent#AXIS_GENERIC_5}. 363 */ 364 public static final int AXIS_GENERIC_5 = 36; 365 366 /** 367 * Synonym for {@link MotionEvent#AXIS_GENERIC_6}. 368 */ 369 public static final int AXIS_GENERIC_6 = 37; 370 371 /** 372 * Synonym for {@link MotionEvent#AXIS_GENERIC_7}. 373 */ 374 public static final int AXIS_GENERIC_7 = 38; 375 376 /** 377 * Synonym for {@link MotionEvent#AXIS_GENERIC_8}. 378 */ 379 public static final int AXIS_GENERIC_8 = 39; 380 381 /** 382 * Synonym for {@link MotionEvent#AXIS_GENERIC_9}. 383 */ 384 public static final int AXIS_GENERIC_9 = 40; 385 386 /** 387 * Synonym for {@link MotionEvent#AXIS_GENERIC_10}. 388 */ 389 public static final int AXIS_GENERIC_10 = 41; 390 391 /** 392 * Synonym for {@link MotionEvent#AXIS_GENERIC_11}. 393 */ 394 public static final int AXIS_GENERIC_11 = 42; 395 396 /** 397 * Synonym for {@link MotionEvent#AXIS_GENERIC_12}. 398 */ 399 public static final int AXIS_GENERIC_12 = 43; 400 401 /** 402 * Synonym for {@link MotionEvent#AXIS_GENERIC_13}. 403 */ 404 public static final int AXIS_GENERIC_13 = 44; 405 406 /** 407 * Synonym for {@link MotionEvent#AXIS_GENERIC_14}. 408 */ 409 public static final int AXIS_GENERIC_14 = 45; 410 411 /** 412 * Synonym for {@link MotionEvent#AXIS_GENERIC_15}. 413 */ 414 public static final int AXIS_GENERIC_15 = 46; 415 416 /** 417 * Synonym for {@link MotionEvent#AXIS_GENERIC_16}. 418 */ 419 public static final int AXIS_GENERIC_16 = 47; 420 421 /** 422 * Call {@link MotionEvent#getAction}, returning only the {@link #ACTION_MASK} 423 * portion. 424 */ 425 public static int getActionMasked(MotionEvent event) { 426 return event.getAction() & ACTION_MASK; 427 } 428 429 /** 430 * Call {@link MotionEvent#getAction}, returning only the pointer index 431 * portion 432 */ 433 public static int getActionIndex(MotionEvent event) { 434 return (event.getAction() & ACTION_POINTER_INDEX_MASK) 435 >> ACTION_POINTER_INDEX_SHIFT; 436 } 437 438 /** 439 * Call {@link MotionEvent#findPointerIndex(int)}. 440 * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device, 441 * does nothing and returns -1. 442 */ 443 public static int findPointerIndex(MotionEvent event, int pointerId) { 444 return IMPL.findPointerIndex(event, pointerId); 445 } 446 447 /** 448 * Call {@link MotionEvent#getPointerId(int)}. 449 * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device, 450 * {@link IndexOutOfBoundsException} is thrown. 451 */ 452 public static int getPointerId(MotionEvent event, int pointerIndex) { 453 return IMPL.getPointerId(event, pointerIndex); 454 } 455 456 /** 457 * Call {@link MotionEvent#getX(int)}. 458 * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device, 459 * {@link IndexOutOfBoundsException} is thrown. 460 */ 461 public static float getX(MotionEvent event, int pointerIndex) { 462 return IMPL.getX(event, pointerIndex); 463 } 464 465 /** 466 * Call {@link MotionEvent#getY(int)}. 467 * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device, 468 * {@link IndexOutOfBoundsException} is thrown. 469 */ 470 public static float getY(MotionEvent event, int pointerIndex) { 471 return IMPL.getY(event, pointerIndex); 472 } 473 474 /** 475 * The number of pointers of data contained in this event. Always 476 * >= 1. 477 */ 478 public static int getPointerCount(MotionEvent event) { 479 return IMPL.getPointerCount(event); 480 } 481 482 /** 483 * Gets the source of the event. 484 * 485 * @return The event source or {@link InputDeviceCompat#SOURCE_UNKNOWN} if unknown. 486 */ 487 public static int getSource(MotionEvent event) { 488 return IMPL.getSource(event); 489 } 490 491 /** 492 * Get axis value for the first pointer index (may be an 493 * arbitrary pointer identifier). 494 * 495 * @param axis The axis identifier for the axis value to retrieve. 496 * 497 * @see #AXIS_X 498 * @see #AXIS_Y 499 */ 500 public static float getAxisValue(MotionEvent event, int axis) { 501 return IMPL.getAxisValue(event, axis); 502 } 503 504 /** 505 * Returns the value of the requested axis for the given pointer <em>index</em> 506 * (use {@link #getPointerId(MotionEvent, int)} to find the pointer identifier for this index). 507 * 508 * @param axis The axis identifier for the axis value to retrieve. 509 * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 510 * (the first pointer that is down) to {@link #getPointerCount(MotionEvent)}-1. 511 * @return The value of the axis, or 0 if the axis is not available. 512 * 513 * @see #AXIS_X 514 * @see #AXIS_Y 515 */ 516 public static float getAxisValue(MotionEvent event, int axis, int pointerIndex) { 517 return IMPL.getAxisValue(event, axis, pointerIndex); 518 } 519} 520