Android——使用InputManager实现模拟滚动
16lz
2022-08-01
文章目录
- 模拟滚动的实现方式
- 具体实现
- 如何使用
模拟滚动的实现方式
Android 提供了集中实现模拟滚动的方式:
Instrumentation
的sendPointerSync()
InputManager
的injectInputEvent()
AccessibilityService
的dispatchGesture()
方法
这篇文章主要是介绍如何利用InputManager
来实现模拟滚动,先看一下效果图:
具体实现
由于injectInputEvent
是@hide
的,所以需要使用反射调用此方法。
public class SwipeEvent { /** * @param fromX 起始x坐标 * @param fromY 起始y坐标 * @param toX 结束x坐标 * @param toY 结束y坐标 * @param step 单次滑动长度 */ public void makeSwipeDown(int fromX, int fromY, int toX, int toY, int step) { InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE); int y = fromY; long downTime = SystemClock.uptimeMillis(); long eventTime = SystemClock.uptimeMillis(); // 模拟down MotionEvent motionEvent = null; motionEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, fromX, fromY, 0); // 将MotionEvent的输入源设置为InputDevice.SOURCE_TOUCHSCREEN,输入源为触摸屏幕 motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); // mode为1,INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT invokeInjectInputEventMethod(inputManager, motionEvent, 1); // 模拟move int stepCount = (fromY - toY) / step; for (int i = 0; i < stepCount; i++) { y -= step; motionEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, fromX, y, 0); motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); // mode为2,INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH invokeInjectInputEventMethod(inputManager, motionEvent, 2); Log.i("cwx", "y:" + y); } // 模拟up if (y <= toY) { motionEvent = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, toX, y, 0); motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN); invokeInjectInputEventMethod(inputManager, motionEvent, 2); } } private void invokeInjectInputEventMethod(InputManager inputManager, InputEvent event, int mode) { Class<?> clazz = null; Method injectInputEventMethod = null; Method recycleMethod = null; try { clazz = Class.forName("android.hardware.input.InputManager"); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { injectInputEventMethod = clazz.getMethod("injectInputEvent", InputEvent.class, int.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } try { injectInputEventMethod.invoke(inputManager, event, mode); // 准备回收event的方法 recycleMethod = event.getClass().getMethod("recycle"); //执行event的recycle方法 recycleMethod.invoke(event); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } }
上面涉及到参数inputSource
,在InputManager
的injectInputEvent
中代表的是mode
,而InputManager
也提供了三种mode
,下面介绍一下:
/** * Input Event Injection Synchronization Mode: None. * Never blocks. Injection is asynchronous and is assumed always to be successful. * 永远不停止,注入输入时异步的,并假设总是成功的。 * @hide */ public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h /** * Input Event Injection Synchronization Mode: Wait for result. * Waits for previous events to be dispatched so that the input dispatcher can * determine whether input event injection will be permitted based on the current * input focus. Does not wait for the input event to finish being handled * by the application. * 等待调度之前的事件,以便调度程序可以根据当前的输入焦点确定是否允许输入事件注入,不必等待程序处理完输入事件。 * @hide */ public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; // see InputDispatcher.h /** * Input Event Injection Synchronization Mode: Wait for finish. * Waits for the event to be delivered to the application and handled. * 等待事件传递到应用程序并进行处理 * @hide */ public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h
如何使用
在由于是模拟滚动,当然比较耗时,我将它放进子线程中执行。
final SwipeEvent swipeEvent = new SwipeEvent();new Thread(new Runnable() { @Override public void run() { swipeEvent.makeSwipeDown(0, 1800, 0, 400, 50); }}).start();
更多相关文章
- Ubuntu下查找.android/avd
- 编译android的linux内核
- 第17天android:《android从零开始》视频(1-5)
- Android(安卓)EditView
- Android(安卓)4.0.1 源码下载,编译和运行
- scrollview 滚动条
- Android(安卓)模拟新浪微博-随便看看栏目
- Android上的模拟点击
- Android下模拟按键输入