62

MotionEvent doesn't get a constructor, I wanted to manually create a MotionEvent in my unit test, then how to get that? Thanks.

fifth
  • 4,249
  • 9
  • 45
  • 62

2 Answers2

103

You should use one of the static obtain methods of the MotionEvent class to create a new event.

The simplest way (besides wrapping a new event from an existing one) is:

static public MotionEvent obtain(long downTime, long eventTime, int action,
        float x, float y, int metaState) {

API Docs:

Create a new MotionEvent, filling in a subset of the basic motion values. Those not specified here are: device id (always 0), pressure and size (always 1), x and y precision (always 1), and edgeFlags (always 0).

Parameters:

  • downTime The time (in ms) when the user originally pressed down to start a stream of position events. This must be obtained from SystemClock.uptimeMillis().
  • eventTime The the time (in ms) when this specific event was generated. This must be obtained from SystemClock.uptimeMillis().
  • action The kind of action being performed -- one of either ACTION_DOWN, ACTION_MOVE, ACTION_UP, or ACTION_CANCEL.
  • x The X coordinate of this event.
  • y The Y coordinate of this event.
  • metaState The state of any meta / modifier keys that were in effect when the event was generated.

Link to API Docs

StefMa
  • 3,344
  • 4
  • 27
  • 48
rekaszeru
  • 19,130
  • 7
  • 59
  • 73
  • 13
    When you're done with them you should always call `recycle` on the MotionEvents that you `obtain`, right? (Maybe not important for unit tests.) I'd guess they're stored in an object pool and obtain and recycle are like new and delete. – idbrii Aug 11 '11 at 20:54
  • 1
    Can somebody confirm recycle is definitely needed? Did not see this from SDK document. – xwz7611 Dec 20 '13 at 21:41
  • 3
    @xwz7611 It isn't needed (basically, `MotionEvent`s have a primitive object cache behind the scenes, and `recycle()` tells the event to store itself in the cache for reuse), but if you don't use it you may gain additional overhead as the VM will have to allocate and construct a new object every time you obtain a `MotionEvent`. (There is a bit of a memory tradeoff as recycled events do still take up space, but as long as you aren't creating a whole bunch of `MotionEvent`s all at once and are dispatching them regularly, that shouldn't be a problem). `ListView` rows do the same automatically. – JAB Mar 14 '14 at 14:15
  • 1
    How can I set the tool type to fake a mouse cursor? – Fernando Gallego May 14 '14 at 08:54
23

Supplemental answer

Here is an example illustrating the accepted answer:

// get the coordinates of the view
int[] coordinates = new int[2];
myView.getLocationOnScreen(coordinates);

// MotionEvent parameters
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
int action = MotionEvent.ACTION_DOWN;
int x = coordinates[0];
int y = coordinates[1];
int metaState = 0;

// dispatch the event
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, metaState);
myView.dispatchTouchEvent(event);
event.recycle();

Notes

  • Other meta states include things like KeyEvent.META_SHIFT_ON, etc.
  • Thanks to this answer for help with the example.
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393