需求:Android模拟器点击上下键,app上下滑动
实现:
- 重写onKeyDown方法
- 创建MotionEvent事件
- 分发MotionEvent(dispatchTouchEvent)
onKeyDown的重写
在Activity中,重写onKeyDown方法
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
moveTaskToBack(false);
return true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {//按向上键
Log.e("KeyUp", "" + event.getSource());
TouchUtil.setMoveToTop(400, this);
return true;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {//按向下键
Log.e("KeyDown", "" + event.getSource());
TouchUtil.setMoveToBottom(400, this);
return true;
}
return super.onKeyDown(keyCode, event);
}
创建MotionEvent事件
通过MotionEvent.obtain()方法创建我们所需要的事件,
MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_DOWN, x, y, 0)
MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, x, y, 0)
MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP, x, y, 0));
分别创建了ACTION_DOWN,ACTION_MOVE,ACTION_UP三个事件,X,Y为当前事件的坐标,SystemClock.uptimeMillis() 为 从开机到现在的毫秒数(手机睡眠的时间不包括在内),最后一个参数metaState,翻译为:生成事件时生效的任何元/修饰键的状态。 native方法中的参数,我们传0(未知)
/**
* 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).
*
* @param downTime The time (in ms) when the user originally pressed down to start
* a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}.
* @param eventTime The the time (in ms) when this specific event was generated. This
* must be obtained from {@link SystemClock#uptimeMillis()}.
* @param action The kind of action being performed, such as {@link #ACTION_DOWN}.
* @param x The X coordinate of this event.
* @param y The Y coordinate of this event.
* @param metaState The state of any meta / modifier keys that were in effect when
* the event was generated.
*/
static public MotionEvent obtain(long downTime, long eventTime, int action,
float x, float y, int metaState) {
return obtain(downTime, eventTime, action, x, y, 1.0f, 1.0f,
metaState, 1.0f, 1.0f, 0, 0);
}
分发MotionEvent
用dispatchTouchEvent来分发上一部创建的MotionEvent
dispatchTouchEvent(MotionEvent ev)
完整代码如下
public class TouchUtil {
private static final String TAG ="TouchUtil";
private static View view;
private static float x;
private static float y;
/**
* 模仿手指点击控件事件
* @param view 控件
* @param x 相对控件的X坐标
* @param y 相对控件的Y坐标
*/
private static void simulateClick(View view, float x, float y) {
TouchUtil.view = view;
TouchUtil.x = x;
TouchUtil.y = y;
long downTime = SystemClock.uptimeMillis();
final MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN, x, y, 0);
downTime += 1000;
final MotionEvent upEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_UP, x, y, 0);
view.onTouchEvent(downEvent);
view.onTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
}
/**
* 模仿手机点击屏幕事件
* @param x X坐标
* @param y Y坐标
* @param activity 传进去的活动对象
*/
public static void setFingerClick(int x, int y, Activity activity){
MotionEvent evenDownt = MotionEvent.obtain(System.currentTimeMillis(),
System.currentTimeMillis() + 100, MotionEvent.ACTION_DOWN, x, y, 0);
activity.dispatchTouchEvent(evenDownt);
MotionEvent eventUp = MotionEvent.obtain(System.currentTimeMillis(),
System.currentTimeMillis() + 100, MotionEvent.ACTION_UP, x, y, 0);
activity.dispatchTouchEvent(eventUp);
evenDownt.recycle();
eventUp.recycle();
Log.d(TAG, "setFingerClick: ");
}
/**
* 模拟向下滑动事件
* @param distance 滑动的距离
* @param activity 传进去的活动对象
*/
public static void setMoveToBottom(int distance,Activity activity){
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_DOWN, 400, 500, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, 400, 500-distance/2, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, 400, 500-distance, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP, 400, 500-distance, 0));
Log.d(TAG, "setMoveToBottom: ");
}
/**
* 模拟向上滑动事件
* @param distance 滑动的距离
* @param activity 传进去的活动对象
*/
public static void setMoveToTop(int distance,Activity activity){
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_DOWN, 400, 500, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, 400, 500+distance/2, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, 400, 500+distance, 0));
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_UP, 400, 500+distance, 0));
Log.d(TAG, "setMoveToTop: ");
}
}
在Activity中调用第一步onKeyDown的重写,可以实现模拟器上下点击,app对应滑动的效果。
如果注释掉这句
activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(),
MotionEvent.ACTION_MOVE, 400, 500-distance/2, 0));
表现为快速滑动,滑动距离大,否则表现为拖动,滑动距离少
参考博客:
模拟手指点击滑动事件
android之DPAD上下左右四个键控制
Android手势处理及模拟滑动事件
Android 模拟触摸动作MotionEvent事件
android 处理鼠标滚轮事件
Android中实现滑动效果