1 /* 2 * Copyright (C) 2007 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 17 package android.test; 18 19 import android.app.Activity; 20 import android.app.Instrumentation; 21 import android.graphics.Point; 22 import android.os.SystemClock; 23 import android.view.Display; 24 import android.view.Gravity; 25 import android.view.MotionEvent; 26 import android.view.View; 27 import android.view.ViewConfiguration; 28 import android.view.ViewGroup; 29 30 /** 31 * Reusable methods for generating touch events. These methods can be used with 32 * InstrumentationTestCase or ActivityInstrumentationTestCase2 to simulate user interaction with 33 * the application through a touch screen. 34 * 35 * @deprecated Use 36 * <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso UI testing 37 * framework</a> instead. New tests should be written using the 38 * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>. 39 */ 40 @Deprecated 41 public class TouchUtils { 42 43 /** 44 * Simulate touching in the center of the screen and dragging one quarter of the way down 45 * @param test The test case that is being run 46 * 47 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 48 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 49 * configuring the Activity under test 50 */ 51 @Deprecated dragQuarterScreenDown(ActivityInstrumentationTestCase test)52 public static void dragQuarterScreenDown(ActivityInstrumentationTestCase test) { 53 dragQuarterScreenDown(test, test.getActivity()); 54 } 55 56 /** 57 * Simulate touching in the center of the screen and dragging one quarter of the way down 58 * @param test The test case that is being run 59 * @param activity The activity that is in the foreground of the test case 60 */ dragQuarterScreenDown(InstrumentationTestCase test, Activity activity)61 public static void dragQuarterScreenDown(InstrumentationTestCase test, Activity activity) { 62 Display display = activity.getWindowManager().getDefaultDisplay(); 63 final Point size = new Point(); 64 display.getSize(size); 65 66 final float x = size.x / 2.0f; 67 final float fromY = size.y * 0.5f; 68 final float toY = size.y * 0.75f; 69 70 drag(test, x, x, fromY, toY, 4); 71 } 72 73 /** 74 * Simulate touching in the center of the screen and dragging one quarter of the way up 75 * @param test The test case that is being run 76 * 77 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 78 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 79 * configuring the Activity under test 80 */ 81 @Deprecated dragQuarterScreenUp(ActivityInstrumentationTestCase test)82 public static void dragQuarterScreenUp(ActivityInstrumentationTestCase test) { 83 dragQuarterScreenUp(test, test.getActivity()); 84 } 85 86 /** 87 * Simulate touching in the center of the screen and dragging one quarter of the way up 88 * @param test The test case that is being run 89 * @param activity The activity that is in the foreground of the test case 90 */ dragQuarterScreenUp(InstrumentationTestCase test, Activity activity)91 public static void dragQuarterScreenUp(InstrumentationTestCase test, Activity activity) { 92 Display display = activity.getWindowManager().getDefaultDisplay(); 93 final Point size = new Point(); 94 display.getSize(size); 95 96 final float x = size.x / 2.0f; 97 final float fromY = size.y * 0.5f; 98 final float toY = size.y * 0.25f; 99 100 drag(test, x, x, fromY, toY, 4); 101 } 102 103 /** 104 * Scroll a ViewGroup to the bottom by repeatedly calling 105 * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)} 106 * 107 * @param test The test case that is being run 108 * @param v The ViewGroup that should be dragged 109 * 110 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 111 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 112 * configuring the Activity under test 113 */ 114 @Deprecated scrollToBottom(ActivityInstrumentationTestCase test, ViewGroup v)115 public static void scrollToBottom(ActivityInstrumentationTestCase test, ViewGroup v) { 116 scrollToBottom(test, test.getActivity(), v); 117 } 118 119 /** 120 * Scroll a ViewGroup to the bottom by repeatedly calling 121 * {@link #dragQuarterScreenUp(InstrumentationTestCase, Activity)} 122 * 123 * @param test The test case that is being run 124 * @param activity The activity that is in the foreground of the test case 125 * @param v The ViewGroup that should be dragged 126 */ scrollToBottom(InstrumentationTestCase test, Activity activity, ViewGroup v)127 public static void scrollToBottom(InstrumentationTestCase test, Activity activity, 128 ViewGroup v) { 129 ViewStateSnapshot prev; 130 ViewStateSnapshot next = new ViewStateSnapshot(v); 131 do { 132 prev = next; 133 TouchUtils.dragQuarterScreenUp(test, activity); 134 next = new ViewStateSnapshot(v); 135 } while (!prev.equals(next)); 136 } 137 138 /** 139 * Scroll a ViewGroup to the top by repeatedly calling 140 * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)} 141 * 142 * @param test The test case that is being run 143 * @param v The ViewGroup that should be dragged 144 * 145 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 146 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 147 * configuring the Activity under test 148 */ 149 @Deprecated scrollToTop(ActivityInstrumentationTestCase test, ViewGroup v)150 public static void scrollToTop(ActivityInstrumentationTestCase test, ViewGroup v) { 151 scrollToTop(test, test.getActivity(), v); 152 } 153 154 /** 155 * Scroll a ViewGroup to the top by repeatedly calling 156 * {@link #dragQuarterScreenDown(InstrumentationTestCase, Activity)} 157 * 158 * @param test The test case that is being run 159 * @param activity The activity that is in the foreground of the test case 160 * @param v The ViewGroup that should be dragged 161 */ scrollToTop(InstrumentationTestCase test, Activity activity, ViewGroup v)162 public static void scrollToTop(InstrumentationTestCase test, Activity activity, ViewGroup v) { 163 ViewStateSnapshot prev; 164 ViewStateSnapshot next = new ViewStateSnapshot(v); 165 do { 166 prev = next; 167 TouchUtils.dragQuarterScreenDown(test, activity); 168 next = new ViewStateSnapshot(v); 169 } while (!prev.equals(next)); 170 } 171 172 /** 173 * Simulate touching the center of a view and dragging to the bottom of the screen. 174 * 175 * @param test The test case that is being run 176 * @param v The view that should be dragged 177 * 178 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 179 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 180 * configuring the Activity under test 181 */ 182 @Deprecated dragViewToBottom(ActivityInstrumentationTestCase test, View v)183 public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v) { 184 dragViewToBottom(test, test.getActivity(), v, 4); 185 } 186 187 /** 188 * Simulate touching the center of a view and dragging to the bottom of the screen. 189 * 190 * @param test The test case that is being run 191 * @param activity The activity that is in the foreground of the test case 192 * @param v The view that should be dragged 193 */ dragViewToBottom(InstrumentationTestCase test, Activity activity, View v)194 public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v) { 195 dragViewToBottom(test, activity, v, 4); 196 } 197 198 /** 199 * Simulate touching the center of a view and dragging to the bottom of the screen. 200 * 201 * @param test The test case that is being run 202 * @param v The view that should be dragged 203 * @param stepCount How many move steps to include in the drag 204 * 205 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 206 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 207 * configuring the Activity under test 208 */ 209 @Deprecated dragViewToBottom(ActivityInstrumentationTestCase test, View v, int stepCount)210 public static void dragViewToBottom(ActivityInstrumentationTestCase test, View v, 211 int stepCount) { 212 dragViewToBottom(test, test.getActivity(), v, stepCount); 213 } 214 215 /** 216 * Simulate touching the center of a view and dragging to the bottom of the screen. 217 * 218 * @param test The test case that is being run 219 * @param activity The activity that is in the foreground of the test case 220 * @param v The view that should be dragged 221 * @param stepCount How many move steps to include in the drag 222 */ dragViewToBottom(InstrumentationTestCase test, Activity activity, View v, int stepCount)223 public static void dragViewToBottom(InstrumentationTestCase test, Activity activity, View v, 224 int stepCount) { 225 int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight(); 226 227 int[] xy = new int[2]; 228 v.getLocationOnScreen(xy); 229 230 final int viewWidth = v.getWidth(); 231 final int viewHeight = v.getHeight(); 232 233 final float x = xy[0] + (viewWidth / 2.0f); 234 float fromY = xy[1] + (viewHeight / 2.0f); 235 float toY = screenHeight - 1; 236 237 drag(test, x, x, fromY, toY, stepCount); 238 } 239 240 /** 241 * Simulate touching the center of a view and releasing quickly (before the tap timeout). 242 * 243 * @param test The test case that is being run 244 * @param v The view that should be clicked 245 */ tapView(InstrumentationTestCase test, View v)246 public static void tapView(InstrumentationTestCase test, View v) { 247 int[] xy = new int[2]; 248 v.getLocationOnScreen(xy); 249 250 final int viewWidth = v.getWidth(); 251 final int viewHeight = v.getHeight(); 252 253 final float x = xy[0] + (viewWidth / 2.0f); 254 float y = xy[1] + (viewHeight / 2.0f); 255 256 Instrumentation inst = test.getInstrumentation(); 257 258 long downTime = SystemClock.uptimeMillis(); 259 long eventTime = SystemClock.uptimeMillis(); 260 261 MotionEvent event = MotionEvent.obtain(downTime, eventTime, 262 MotionEvent.ACTION_DOWN, x, y, 0); 263 inst.sendPointerSync(event); 264 inst.waitForIdleSync(); 265 266 eventTime = SystemClock.uptimeMillis(); 267 final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); 268 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 269 x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0); 270 inst.sendPointerSync(event); 271 inst.waitForIdleSync(); 272 273 eventTime = SystemClock.uptimeMillis(); 274 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); 275 inst.sendPointerSync(event); 276 inst.waitForIdleSync(); 277 } 278 279 /** 280 * Simulate touching the center of a view and cancelling (so no onClick should 281 * fire, etc). 282 * 283 * @param test The test case that is being run 284 * @param v The view that should be clicked 285 */ touchAndCancelView(InstrumentationTestCase test, View v)286 public static void touchAndCancelView(InstrumentationTestCase test, View v) { 287 int[] xy = new int[2]; 288 v.getLocationOnScreen(xy); 289 290 final int viewWidth = v.getWidth(); 291 final int viewHeight = v.getHeight(); 292 293 final float x = xy[0] + (viewWidth / 2.0f); 294 float y = xy[1] + (viewHeight / 2.0f); 295 296 Instrumentation inst = test.getInstrumentation(); 297 298 long downTime = SystemClock.uptimeMillis(); 299 long eventTime = SystemClock.uptimeMillis(); 300 301 MotionEvent event = MotionEvent.obtain(downTime, eventTime, 302 MotionEvent.ACTION_DOWN, x, y, 0); 303 inst.sendPointerSync(event); 304 inst.waitForIdleSync(); 305 306 eventTime = SystemClock.uptimeMillis(); 307 final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); 308 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_CANCEL, 309 x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0); 310 inst.sendPointerSync(event); 311 inst.waitForIdleSync(); 312 313 } 314 315 /** 316 * Simulate touching the center of a view and releasing. 317 * 318 * @param test The test case that is being run 319 * @param v The view that should be clicked 320 */ clickView(InstrumentationTestCase test, View v)321 public static void clickView(InstrumentationTestCase test, View v) { 322 int[] xy = new int[2]; 323 v.getLocationOnScreen(xy); 324 325 final int viewWidth = v.getWidth(); 326 final int viewHeight = v.getHeight(); 327 328 final float x = xy[0] + (viewWidth / 2.0f); 329 float y = xy[1] + (viewHeight / 2.0f); 330 331 Instrumentation inst = test.getInstrumentation(); 332 333 long downTime = SystemClock.uptimeMillis(); 334 long eventTime = SystemClock.uptimeMillis(); 335 336 MotionEvent event = MotionEvent.obtain(downTime, eventTime, 337 MotionEvent.ACTION_DOWN, x, y, 0); 338 inst.sendPointerSync(event); 339 inst.waitForIdleSync(); 340 341 342 eventTime = SystemClock.uptimeMillis(); 343 final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); 344 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 345 x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0); 346 inst.sendPointerSync(event); 347 inst.waitForIdleSync(); 348 349 eventTime = SystemClock.uptimeMillis(); 350 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); 351 inst.sendPointerSync(event); 352 inst.waitForIdleSync(); 353 354 try { 355 Thread.sleep(1000); 356 } catch (InterruptedException e) { 357 e.printStackTrace(); 358 } 359 } 360 361 /** 362 * Simulate touching the center of a view, holding until it is a long press, and then releasing. 363 * 364 * @param test The test case that is being run 365 * @param v The view that should be clicked 366 * 367 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 368 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 369 * configuring the Activity under test 370 */ 371 @Deprecated longClickView(ActivityInstrumentationTestCase test, View v)372 public static void longClickView(ActivityInstrumentationTestCase test, View v) { 373 longClickView((InstrumentationTestCase) test, v); 374 } 375 376 /** 377 * Simulate touching the center of a view, holding until it is a long press, and then releasing. 378 * 379 * @param test The test case that is being run 380 * @param v The view that should be clicked 381 */ longClickView(InstrumentationTestCase test, View v)382 public static void longClickView(InstrumentationTestCase test, View v) { 383 int[] xy = new int[2]; 384 v.getLocationOnScreen(xy); 385 386 final int viewWidth = v.getWidth(); 387 final int viewHeight = v.getHeight(); 388 389 final float x = xy[0] + (viewWidth / 2.0f); 390 float y = xy[1] + (viewHeight / 2.0f); 391 392 Instrumentation inst = test.getInstrumentation(); 393 394 long downTime = SystemClock.uptimeMillis(); 395 long eventTime = SystemClock.uptimeMillis(); 396 397 MotionEvent event = MotionEvent.obtain(downTime, eventTime, 398 MotionEvent.ACTION_DOWN, x, y, 0); 399 inst.sendPointerSync(event); 400 inst.waitForIdleSync(); 401 402 eventTime = SystemClock.uptimeMillis(); 403 final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop(); 404 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, 405 x + touchSlop / 2, y + touchSlop / 2, 0); 406 inst.sendPointerSync(event); 407 inst.waitForIdleSync(); 408 409 try { 410 Thread.sleep((long)(ViewConfiguration.getLongPressTimeout() * 1.5f)); 411 } catch (InterruptedException e) { 412 e.printStackTrace(); 413 } 414 415 eventTime = SystemClock.uptimeMillis(); 416 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); 417 inst.sendPointerSync(event); 418 inst.waitForIdleSync(); 419 } 420 421 /** 422 * Simulate touching the center of a view and dragging to the top of the screen. 423 * 424 * @param test The test case that is being run 425 * @param v The view that should be dragged 426 * 427 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 428 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 429 * configuring the Activity under test 430 */ 431 @Deprecated dragViewToTop(ActivityInstrumentationTestCase test, View v)432 public static void dragViewToTop(ActivityInstrumentationTestCase test, View v) { 433 dragViewToTop((InstrumentationTestCase) test, v, 4); 434 } 435 436 /** 437 * Simulate touching the center of a view and dragging to the top of the screen. 438 * 439 * @param test The test case that is being run 440 * @param v The view that should be dragged 441 * @param stepCount How many move steps to include in the drag 442 * 443 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 444 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 445 * configuring the Activity under test 446 */ 447 @Deprecated dragViewToTop(ActivityInstrumentationTestCase test, View v, int stepCount)448 public static void dragViewToTop(ActivityInstrumentationTestCase test, View v, int stepCount) { 449 dragViewToTop((InstrumentationTestCase) test, v, stepCount); 450 } 451 452 /** 453 * Simulate touching the center of a view and dragging to the top of the screen. 454 * 455 * @param test The test case that is being run 456 * @param v The view that should be dragged 457 */ dragViewToTop(InstrumentationTestCase test, View v)458 public static void dragViewToTop(InstrumentationTestCase test, View v) { 459 dragViewToTop(test, v, 4); 460 } 461 462 /** 463 * Simulate touching the center of a view and dragging to the top of the screen. 464 * 465 * @param test The test case that is being run 466 * @param v The view that should be dragged 467 * @param stepCount How many move steps to include in the drag 468 */ dragViewToTop(InstrumentationTestCase test, View v, int stepCount)469 public static void dragViewToTop(InstrumentationTestCase test, View v, int stepCount) { 470 int[] xy = new int[2]; 471 v.getLocationOnScreen(xy); 472 473 final int viewWidth = v.getWidth(); 474 final int viewHeight = v.getHeight(); 475 476 final float x = xy[0] + (viewWidth / 2.0f); 477 float fromY = xy[1] + (viewHeight / 2.0f); 478 float toY = 0; 479 480 drag(test, x, x, fromY, toY, stepCount); 481 } 482 483 /** 484 * Get the location of a view. Use the gravity param to specify which part of the view to 485 * return. 486 * 487 * @param v View to find 488 * @param gravity A combination of (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, 489 * RIGHT) 490 * @param xy Result 491 */ getStartLocation(View v, int gravity, int[] xy)492 private static void getStartLocation(View v, int gravity, int[] xy) { 493 v.getLocationOnScreen(xy); 494 495 final int viewWidth = v.getWidth(); 496 final int viewHeight = v.getHeight(); 497 498 switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) { 499 case Gravity.TOP: 500 break; 501 case Gravity.CENTER_VERTICAL: 502 xy[1] += viewHeight / 2; 503 break; 504 case Gravity.BOTTOM: 505 xy[1] += viewHeight - 1; 506 break; 507 default: 508 // Same as top -- do nothing 509 } 510 511 switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { 512 case Gravity.LEFT: 513 break; 514 case Gravity.CENTER_HORIZONTAL: 515 xy[0] += viewWidth / 2; 516 break; 517 case Gravity.RIGHT: 518 xy[0] += viewWidth - 1; 519 break; 520 default: 521 // Same as left -- do nothing 522 } 523 } 524 525 /** 526 * Simulate touching a view and dragging it by the specified amount. 527 * 528 * @param test The test case that is being run 529 * @param v The view that should be dragged 530 * @param gravity Which part of the view to use for the initial down event. A combination of 531 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 532 * @param deltaX Amount to drag horizontally in pixels 533 * @param deltaY Amount to drag vertically in pixels 534 * 535 * @return distance in pixels covered by the drag 536 * 537 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 538 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 539 * configuring the Activity under test 540 */ 541 @Deprecated dragViewBy(ActivityInstrumentationTestCase test, View v, int gravity, int deltaX, int deltaY)542 public static int dragViewBy(ActivityInstrumentationTestCase test, View v, int gravity, 543 int deltaX, int deltaY) { 544 return dragViewBy((InstrumentationTestCase) test, v, gravity, deltaX, deltaY); 545 } 546 547 /** 548 * Simulate touching a view and dragging it by the specified amount. 549 * 550 * @param test The test case that is being run 551 * @param v The view that should be dragged 552 * @param gravity Which part of the view to use for the initial down event. A combination of 553 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 554 * @param deltaX Amount to drag horizontally in pixels 555 * @param deltaY Amount to drag vertically in pixels 556 * 557 * @return distance in pixels covered by the drag 558 * 559 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 560 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 561 * configuring the Activity under test 562 */ 563 @Deprecated dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX, int deltaY)564 public static int dragViewBy(InstrumentationTestCase test, View v, int gravity, int deltaX, 565 int deltaY) { 566 int[] xy = new int[2]; 567 568 getStartLocation(v, gravity, xy); 569 570 final int fromX = xy[0]; 571 final int fromY = xy[1]; 572 573 int distance = (int) Math.hypot(deltaX, deltaY); 574 575 drag(test, fromX, fromX + deltaX, fromY, fromY + deltaY, distance); 576 577 return distance; 578 } 579 580 /** 581 * Simulate touching a view and dragging it to a specified location. 582 * 583 * @param test The test case that is being run 584 * @param v The view that should be dragged 585 * @param gravity Which part of the view to use for the initial down event. A combination of 586 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 587 * @param toX Final location of the view after dragging 588 * @param toY Final location of the view after dragging 589 * 590 * @return distance in pixels covered by the drag 591 * 592 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 593 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 594 * configuring the Activity under test 595 */ 596 @Deprecated dragViewTo(ActivityInstrumentationTestCase test, View v, int gravity, int toX, int toY)597 public static int dragViewTo(ActivityInstrumentationTestCase test, View v, int gravity, int toX, 598 int toY) { 599 return dragViewTo((InstrumentationTestCase) test, v, gravity, toX, toY); 600 } 601 602 /** 603 * Simulate touching a view and dragging it to a specified location. 604 * 605 * @param test The test case that is being run 606 * @param v The view that should be dragged 607 * @param gravity Which part of the view to use for the initial down event. A combination of 608 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 609 * @param toX Final location of the view after dragging 610 * @param toY Final location of the view after dragging 611 * 612 * @return distance in pixels covered by the drag 613 */ dragViewTo(InstrumentationTestCase test, View v, int gravity, int toX, int toY)614 public static int dragViewTo(InstrumentationTestCase test, View v, int gravity, int toX, 615 int toY) { 616 int[] xy = new int[2]; 617 618 getStartLocation(v, gravity, xy); 619 620 final int fromX = xy[0]; 621 final int fromY = xy[1]; 622 623 int deltaX = fromX - toX; 624 int deltaY = fromY - toY; 625 626 int distance = (int)Math.hypot(deltaX, deltaY); 627 drag(test, fromX, toX, fromY, toY, distance); 628 629 return distance; 630 } 631 632 /** 633 * Simulate touching a view and dragging it to a specified location. Only moves horizontally. 634 * 635 * @param test The test case that is being run 636 * @param v The view that should be dragged 637 * @param gravity Which part of the view to use for the initial down event. A combination of 638 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 639 * @param toX Final location of the view after dragging 640 * 641 * @return distance in pixels covered by the drag 642 * 643 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 644 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 645 * configuring the Activity under test 646 */ 647 @Deprecated dragViewToX(ActivityInstrumentationTestCase test, View v, int gravity, int toX)648 public static int dragViewToX(ActivityInstrumentationTestCase test, View v, int gravity, 649 int toX) { 650 return dragViewToX((InstrumentationTestCase) test, v, gravity, toX); 651 } 652 653 /** 654 * Simulate touching a view and dragging it to a specified location. Only moves horizontally. 655 * 656 * @param test The test case that is being run 657 * @param v The view that should be dragged 658 * @param gravity Which part of the view to use for the initial down event. A combination of 659 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 660 * @param toX Final location of the view after dragging 661 * 662 * @return distance in pixels covered by the drag 663 */ dragViewToX(InstrumentationTestCase test, View v, int gravity, int toX)664 public static int dragViewToX(InstrumentationTestCase test, View v, int gravity, int toX) { 665 int[] xy = new int[2]; 666 667 getStartLocation(v, gravity, xy); 668 669 final int fromX = xy[0]; 670 final int fromY = xy[1]; 671 672 int deltaX = fromX - toX; 673 674 drag(test, fromX, toX, fromY, fromY, deltaX); 675 676 return deltaX; 677 } 678 679 /** 680 * Simulate touching a view and dragging it to a specified location. Only moves vertically. 681 * 682 * @param test The test case that is being run 683 * @param v The view that should be dragged 684 * @param gravity Which part of the view to use for the initial down event. A combination of 685 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 686 * @param toY Final location of the view after dragging 687 * 688 * @return distance in pixels covered by the drag 689 * 690 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 691 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 692 * configuring the Activity under test 693 */ 694 @Deprecated dragViewToY(ActivityInstrumentationTestCase test, View v, int gravity, int toY)695 public static int dragViewToY(ActivityInstrumentationTestCase test, View v, int gravity, 696 int toY) { 697 return dragViewToY((InstrumentationTestCase) test, v, gravity, toY); 698 } 699 700 /** 701 * Simulate touching a view and dragging it to a specified location. Only moves vertically. 702 * 703 * @param test The test case that is being run 704 * @param v The view that should be dragged 705 * @param gravity Which part of the view to use for the initial down event. A combination of 706 * (TOP, CENTER_VERTICAL, BOTTOM) and (LEFT, CENTER_HORIZONTAL, RIGHT) 707 * @param toY Final location of the view after dragging 708 * 709 * @return distance in pixels covered by the drag 710 */ dragViewToY(InstrumentationTestCase test, View v, int gravity, int toY)711 public static int dragViewToY(InstrumentationTestCase test, View v, int gravity, int toY) { 712 int[] xy = new int[2]; 713 714 getStartLocation(v, gravity, xy); 715 716 final int fromX = xy[0]; 717 final int fromY = xy[1]; 718 719 int deltaY = fromY - toY; 720 721 drag(test, fromX, fromX, fromY, toY, deltaY); 722 723 return deltaY; 724 } 725 726 727 /** 728 * Simulate touching a specific location and dragging to a new location. 729 * 730 * @param test The test case that is being run 731 * @param fromX X coordinate of the initial touch, in screen coordinates 732 * @param toX Xcoordinate of the drag destination, in screen coordinates 733 * @param fromY X coordinate of the initial touch, in screen coordinates 734 * @param toY Y coordinate of the drag destination, in screen coordinates 735 * @param stepCount How many move steps to include in the drag 736 * 737 * @deprecated {@link android.test.ActivityInstrumentationTestCase} is deprecated in favor of 738 * {@link android.test.ActivityInstrumentationTestCase2}, which provides more options for 739 * configuring the Activity under test 740 */ 741 @Deprecated drag(ActivityInstrumentationTestCase test, float fromX, float toX, float fromY, float toY, int stepCount)742 public static void drag(ActivityInstrumentationTestCase test, float fromX, float toX, 743 float fromY, float toY, int stepCount) { 744 drag((InstrumentationTestCase) test, fromX, toX, fromY, toY, stepCount); 745 } 746 747 /** 748 * Simulate touching a specific location and dragging to a new location. 749 * 750 * @param test The test case that is being run 751 * @param fromX X coordinate of the initial touch, in screen coordinates 752 * @param toX Xcoordinate of the drag destination, in screen coordinates 753 * @param fromY X coordinate of the initial touch, in screen coordinates 754 * @param toY Y coordinate of the drag destination, in screen coordinates 755 * @param stepCount How many move steps to include in the drag 756 */ drag(InstrumentationTestCase test, float fromX, float toX, float fromY, float toY, int stepCount)757 public static void drag(InstrumentationTestCase test, float fromX, float toX, float fromY, 758 float toY, int stepCount) { 759 Instrumentation inst = test.getInstrumentation(); 760 761 long downTime = SystemClock.uptimeMillis(); 762 long eventTime = SystemClock.uptimeMillis(); 763 764 float y = fromY; 765 float x = fromX; 766 767 float yStep = (toY - fromY) / stepCount; 768 float xStep = (toX - fromX) / stepCount; 769 770 MotionEvent event = MotionEvent.obtain(downTime, eventTime, 771 MotionEvent.ACTION_DOWN, x, y, 0); 772 inst.sendPointerSync(event); 773 for (int i = 0; i < stepCount; ++i) { 774 y += yStep; 775 x += xStep; 776 eventTime = SystemClock.uptimeMillis(); 777 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0); 778 inst.sendPointerSync(event); 779 } 780 781 eventTime = SystemClock.uptimeMillis(); 782 event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); 783 inst.sendPointerSync(event); 784 inst.waitForIdleSync(); 785 } 786 787 private static class ViewStateSnapshot { 788 final View mFirst; 789 final View mLast; 790 final int mFirstTop; 791 final int mLastBottom; 792 final int mChildCount; ViewStateSnapshot(ViewGroup viewGroup)793 private ViewStateSnapshot(ViewGroup viewGroup) { 794 mChildCount = viewGroup.getChildCount(); 795 if (mChildCount == 0) { 796 mFirst = mLast = null; 797 mFirstTop = mLastBottom = Integer.MIN_VALUE; 798 } else { 799 mFirst = viewGroup.getChildAt(0); 800 mLast = viewGroup.getChildAt(mChildCount - 1); 801 mFirstTop = mFirst.getTop(); 802 mLastBottom = mLast.getBottom(); 803 } 804 } 805 806 @Override equals(Object o)807 public boolean equals(Object o) { 808 if (this == o) { 809 return true; 810 } 811 if (o == null || getClass() != o.getClass()) { 812 return false; 813 } 814 815 final ViewStateSnapshot that = (ViewStateSnapshot) o; 816 return mFirstTop == that.mFirstTop && 817 mLastBottom == that.mLastBottom && 818 mFirst == that.mFirst && 819 mLast == that.mLast && 820 mChildCount == that.mChildCount; 821 } 822 823 @Override hashCode()824 public int hashCode() { 825 int result = mFirst != null ? mFirst.hashCode() : 0; 826 result = 31 * result + (mLast != null ? mLast.hashCode() : 0); 827 result = 31 * result + mFirstTop; 828 result = 31 * result + mLastBottom; 829 result = 31 * result + mChildCount; 830 return result; 831 } 832 } 833 } 834