add docs and samples for events module

This commit is contained in:
hyb1996
2017-07-20 22:03:21 +08:00
parent 52cc5214f1
commit 85216477c4
15 changed files with 555 additions and 49 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "com.stardust.scriptdroid" applicationId "com.stardust.scriptdroid"
minSdkVersion 17 minSdkVersion 17
targetSdkVersion 23 targetSdkVersion 23
versionCode 151 versionCode 152
versionName "2.0.14 Beta2.1" versionName "2.0.15 Alpha"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {

View File

@@ -49,6 +49,11 @@
"type": "markdown", "type": "markdown",
"path":"documentation" "path":"documentation"
}, },
{
"title": "事件与按键、触摸监听",
"type": "markdown",
"path":"documentation"
},
{ {
"title": "shell命令", "title": "shell命令",
"type": "markdown", "type": "markdown",

View File

@@ -0,0 +1,384 @@
目录:
* [events](#events)
* [EventEmitter](#EventEmitter)
* [KeyEvent](#KeyEvent)
# events
events也是一个\[EventEmitter\](#EventEmitter)可以使用EventEmitter的所有函数这里只介绍其自身的函数。
### events.emitter()
返回一个新的EventEmitter。
### events.observeKey()
启用按键监听例如音量键、Home键。
在安卓4.3以上才能使用。
### events.loop()
开始事件处理循环。**在events注册按键、触摸事件监听后必须调用该函数开始事件处理循环否则相应事件发生时不会处理。**
该函数是一个"死循环",调用后后面的语句将不再执行。
例子:
```
events.observeKey();
events.onKeyDown("volume_up", function(event){
toast("音量上键被按下了");
});
events.onKeyDown("menu", function(event){
toast("菜单键被按下了");
});
events.loop();
//后面的语句不会再执行了
```
### events.onKeyDown(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个[KeyEvent](#KeyEvent)
注册一个按键监听函数当有keyName对应的按键被按下会调用该函数。按键名称主要包括
* volume_up 音量上键
* volume_down 音量下键
* home 主屏幕键
* back 返回键
* menu 菜单键
### events.onKeyUp(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个[KeyEvent](#KeyEvent)
注册一个按键监听函数当有keyName对应的按键弹起时会调用该函数。
### events.onceKeyDown(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个[KeyEvent](#KeyEvent)
注册一个按键监听函数当有keyName对应的按键被按下时会调用该函数之后会注销该按键监听。也就是listener只会被调用一次。
### events.onceKeyUp(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个[KeyEvent](#KeyEvent)
注册一个按键监听函数当有keyName对应的按键弹起时会调用该函数之后会注销该按键监听。也就是listener只会被调用一次。
### events.removeAllKeyDownListeners(keyName)
* keyName \<String\> 按键名称
删除该按键的KeyDown事件的所有监听。
### events.removeAllKeyUpListeners(keyName)
* keyName \<String\> 按键名称
删除该按键的KeyUp事件的所有监听。
### events.observeTouch()
启用屏幕触摸监听。需要root权限
### events.setTouchEventTimeout(timeout)
* timeout \<Number\> 两个触摸事件的最小间隔。单位毫秒。默认为10毫秒。
设置两个触摸事件分发的最小时间间隔。
例如间隔为10毫秒的话前一个触摸事件发生并被注册的监听器处理后至少要过10毫秒才能分发和处理下一个触摸事件这10毫秒之间的触摸将会被忽略。
### events.getTouchEventTimeout()
返回触摸事件的最小时间间隔。
### events.onTouch(listener)
* listener \<Function\> 参数为(x, y)的函数
注册一个触摸监听函数。
例如:
```
events.observeTouch();
events.onTouch(function(x, y){
log(x + ", " + y);
});
events.loop();
```
### events.removeAllTouchListeners()
删除所有事件监听函数。
### key事件
当有按键被按下或弹起时会触发该事件。
```
"auto";
events.observeKey();
events.on("key", function(keyCode, event){
//处理按键事件
});
events.loop();
```
其中监听器的参数KeyCode包括
* KeyEvent.KEYCODE_HOME 主页键
* KeyEvent.KEYCODE_BACK 返回键
* KeyEvent.KEYCODE_MENU 菜单键
* KeyEvent.KEYCODE_VOLUME_UP 音量上键
* KeyEvent.KEYCODE_VOLUME_DOWN 音量下键
### key_down事件
当有按键被按下时会触发该事件。
```
"auto";
events.observeKey();
events.on("key_down", function(keyCode, event){
//处理按键按下事件
});
events.loop();
```
### key_up事件
当有按键弹起时会触发该事件。
```
"auto";
events.observeKey();
events.on("key_up", function(keyCode, event){
//处理按键弹起事件
});
events.loop();
```
# EventEmitter
### EventEmitter.defaultMaxListeners
每个事件默认可以注册最多 10 个监听器。 单个 EventEmitter 实例的限制可以使用 emitter.setMaxListeners(n) 方法改变。 所有 EventEmitter 实例的默认值可以使用 EventEmitter.defaultMaxListeners 属性改变。
设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。
注意与NodeJs不同**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器监听器超过最大数量时会抛出TooManyListenersException。
```
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// 做些操作
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
```
## EventEmitter.addListener(eventName, listener)
* eventName \<any\>
* listener \<Function\>
emitter.on(eventName, listener) 的别名。
### EventEmitter.emit(eventName\[, ...args\])
* eventName <any>
* args <any>
按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。
如果事件有监听器,则返回 true ,否则返回 false。
### EventEmitter.eventNames()
返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。
```
const myEE = events.emitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// 打印: [ 'foo', 'bar', Symbol(symbol) ]
```
### EventEmitter.getMaxListeners()#
返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners。
### EventEmitter.listenerCount(eventName)
* eventName <any> 正在被监听的事件名
返回正在监听名为 eventName 的事件的监听器的数量。
### EventEmitter.listeners(eventName)
* eventName <any>
返回名为 eventName 的事件的监听器数组的副本。
```
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// 打印: [ [Function] ]
```
### EventEmitter.on(eventName, listener)
* eventName <any> 事件名
* listener <Function> 回调函数
添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。
```
server.on('connection', (stream) => {
console.log('有连接!');
});
```
返回一个 EventEmitter 引用,可以链式调用。
默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头。
```
const myEE = events.emitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
// b
// a
```
### EventEmitter.once(eventName, listener)#
* eventName <any> 事件名
* listener <Function> 回调函数
添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。
```
server.once('connection', (stream) => {
console.log('首次调用!');
});
```
返回一个 EventEmitter 引用,可以链式调用。
默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。
```
const myEE = events.emitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
// b
// a
```
### EventEmitter.prependListener(eventName, listener)
* eventName <any> 事件名
* listener <Function> 回调函数
添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。
```
server.prependListener('connection', (stream) => {
console.log('有连接!');
});
```
返回一个 EventEmitter 引用,可以链式调用。
### EventEmitter.prependOnceListener(eventName, listener)
* eventName <any> 事件名
* listener <Function> 回调函数
添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。
```
server.prependOnceListener('connection', (stream) => {
console.log('首次调用!');
});
```
返回一个 EventEmitter 引用,可以链式调用。
### EventEmitter.removeAllListeners(\[eventName\])
* eventName <any>
移除全部或指定 eventName 的监听器。
注意,在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块创建的。
返回一个 EventEmitter 引用,可以链式调用。
### EventEmitter.removeListener(eventName, listener)
* eventName <any>
* listener <Function>
从名为 eventName 的事件的监听器数组中移除指定的 listener。
```
const callback = (stream) => {
console.log('有连接!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
```
removeListener 最多只会从监听器数组里移除一个监听器实例。 如果任何单一的监听器被多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener 才能移除每个实例。
注意,一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。 这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生。
```
const myEmitter = events.emitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA 移除了监听器 callbackB但它依然会被调用。
// 触发是内部的监听器数组为 [callbackA, callbackB]
myEmitter.emit('event');
// 打印:
// A
// B
// callbackB 被移除了。
// 内部监听器数组为 [callbackA]
myEmitter.emit('event');
// 打印:
// A
```
因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建。
返回一个 EventEmitter 引用,可以链式调用。
### EventEmitter.setMaxListeners(n)
* n <integer>
默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity或 0表明不限制监听器的数量。
返回一个 EventEmitter 引用,可以链式调用。
# KeyEvent
### KeyEvent.getAction()
返回事件的动作。包括:
* KeyEvent.ACTION_DOWN 按下事件
* KeyEvent.ACTION_UP 弹起事件
### KeyEvent.getKeyCode()
返回按键的键值。包括:
* KeyEvent.KEYCODE_HOME 主页键
* KeyEvent.KEYCODE_BACK 返回键
* KeyEvent.KEYCODE_MENU 菜单键
* KeyEvent.KEYCODE_VOLUME_UP 音量上键
* KeyEvent.KEYCODE_VOLUME_DOWN 音量下键
### KeyEvent.getEventTime()
返回事件发生的时间戳。
### KeyEvent.getDownTime()
返回最近一次按下事件的时间戳。如果本身是按下事件则与getEventTime()相同。
### KeyEvent.keyCodeToString(keyCode)
把键值转换为字符串。例如KEYCODE_HOME转换为"KEYCODE_HOME"。

View File

@@ -1,20 +0,0 @@
# events
events也是一个\[EventEmitter\],这里只介绍其自身的函数。
### events.emitter()
返回一个新的EventEmitter。
### events.observeKey()
启用按键监听例如音量键、Home键。
在安卓4.3以上才能使用。
### events.onKeyDown(keyName, listener)
* keyName \<String\> 要监听的按键名称
* listener \<Function\> 参数为一个\[KeyEvent\]
注册一个按键监听函数,。按键名称包括

View File

@@ -27,6 +27,7 @@ while(true){
addAsFriend(); addAsFriend();
sleep(延迟); sleep(延迟);
} }
list.scrollForward();
} }
function isGroupMember(child){ function isGroupMember(child){

View File

@@ -7,5 +7,5 @@ sleep(500);
while(true){ while(true){
setText("我喜欢你"); setText("我喜欢你");
click("发送"); click("发送");
sleep(200); sleep(100);
} }

View File

@@ -0,0 +1,34 @@
"auto";
events.observeKey();
var keyNames = {
"KEYCODE_VOLUME_UP": "音量上键",
"KEYCODE_VOLUME_DOWN": "音量下键",
"KEYCODE_HOME": "Home键",
"KEYCODE_BACK": "返回键",
"KEYCODE_MENU": "菜单键",
"KEYCODE_POWER": "电源键",
};
events.on("key", function(code, event){
var keyName = getKeyName(code, event);
if(event.getAction() == event.ACTION_DOWN){
toast(keyName + "被按下");
}else if(event.getAction() == event.ACTION_UP){
toast(keyName + "弹起");
}
});
events.loop();
function getKeyName(code, event){
var keyCodeStr = event.keyCodeToString(code);
var keyName = keyNames[keyCodeStr];
if(!keyName){
return keyCodeStr;
}
return keyName;
}

View File

@@ -0,0 +1,12 @@
events.observeTouch();
events.setTouchEventTimeout(30);
toast("请在日志中查看触摸的点的坐标");
events.on("touch", function(point){
log(point);
});
events.loop();

View File

@@ -0,0 +1,35 @@
"auto";
var 长按间隔 = 1500;
var curPackage = null;
var backPressedCount = 0;
var backPressed = false;
events.observeKey();
events.onKeyDown("back", function(event){
curPackage = currentPackage();
backPressed = true;
backPressedCount++;
(function(count){
events.setTimeout(function(){
if(backPressed && count == backPressedCount){
backBackBackBack();
}
}, 长按间隔);
})(backPressedCount);
});
events.onKeyUp("back", function(event){
backPressed = false;
});
events.loop();
function backBackBackBack(){
while(curPackage == currentPackage()){
back();
sleep(200);
}
}

View File

@@ -0,0 +1,34 @@
"auto";
events.observeKey();
var interval = 5000;
var task = task1;
events.onKeyDown("volume_up", function(event){
if(task == task1){
task = task2;
}else{
task = task1;
}
toast("任务已切换");
});
events.onKeyDown("volume_down", function(event){
stop();
toast("程序结束");
});
task();
events.loop();
function task1(){
toast("任务1运行中音量下键结束音量上键切换任务");
events.setTimeout(task, interval);
}
function task2(){
toast("任务2运行中音量下键结束音量上键切换任务");
events.setTimeout(task, interval);
}

View File

@@ -6,6 +6,7 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.view.KeyEvent;
import com.stardust.app.OnActivityResultDelegate; import com.stardust.app.OnActivityResultDelegate;
import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.app.SimpleActivityLifecycleCallbacks;

View File

@@ -35,5 +35,6 @@ require("__general__")(__runtime__, this);
} }
})(__that__); })(__that__);
__importClass__(android.view.KeyEvent);
__importClass__(com.stardust.autojs.runtime.api.Shell); __importClass__(com.stardust.autojs.runtime.api.Shell);
__importClass__(com.stardust.autojs.runtime.api.InputEventSender); __importClass__(com.stardust.autojs.runtime.api.InputEventSender);

View File

@@ -54,19 +54,13 @@ public class EventEmitter {
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator(); Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
while (listenerIterator.hasNext()) { while (listenerIterator.hasNext()) {
ListenerWrapper listenerWrapper = listenerIterator.next(); ListenerWrapper listenerWrapper = listenerIterator.next();
onEvent(listenerWrapper, args); call(listenerWrapper.listener, args);
if (listenerWrapper.isOnce) { if (listenerWrapper.isOnce) {
listenerIterator.remove(); listenerIterator.remove();
} }
} }
} }
private void onEvent(ListenerWrapper listenerWrapper, Object[] args) {
if (mFunctionCaller != null) {
mFunctionCaller.call(listenerWrapper.listener, args);
}
}
int count() { int count() {
return mListenerWrappers.size(); return mListenerWrappers.size();
} }
@@ -98,7 +92,8 @@ public class EventEmitter {
} }
private Map<String, Listeners> mListenersMap = new HashMap<>(); private Map<String, Listeners> mListenersMap = new HashMap<>();
private int mMaxListeners = defaultMaxListeners(); public static int defaultMaxListeners = 10;
private int mMaxListeners = defaultMaxListeners;
private FunctionCaller mFunctionCaller; private FunctionCaller mFunctionCaller;
public EventEmitter once(String eventName, Object listener) { public EventEmitter once(String eventName, Object listener) {
@@ -186,10 +181,17 @@ public class EventEmitter {
} }
public static int defaultMaxListeners() { public static int defaultMaxListeners() {
return 0; return defaultMaxListeners;
} }
public void setFunctionCaller(FunctionCaller functionCaller) { public void setFunctionCaller(FunctionCaller functionCaller) {
mFunctionCaller = functionCaller; mFunctionCaller = functionCaller;
} }
protected void call(Object func, Object[] args) {
if (mFunctionCaller != null) {
mFunctionCaller.call(func, args);
}
}
} }

View File

@@ -1,14 +1,14 @@
package com.stardust.autojs.runtime.api; package com.stardust.autojs.runtime.api;
import android.content.Context; import android.content.Context;
import android.graphics.Point;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.method.KeyListener; import android.util.SparseArray;
import android.view.KeyEvent; import android.view.KeyEvent;
import com.stardust.autojs.runtime.AccessibilityBridge; import com.stardust.autojs.runtime.AccessibilityBridge;
import com.stardust.autojs.runtime.ScriptStopException; import com.stardust.autojs.runtime.ScriptStopException;
import com.stardust.autojs.runtime.record.inputevent.InputEventRecorder;
import com.stardust.autojs.runtime.record.inputevent.TouchObserver; import com.stardust.autojs.runtime.record.inputevent.TouchObserver;
import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.OnKeyListener; import com.stardust.view.accessibility.OnKeyListener;
@@ -23,15 +23,16 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
private static final String PREFIX_KEY_DOWN = "__key_down__#"; private static final String PREFIX_KEY_DOWN = "__key_down__#";
private static final String PREFIX_KEY_UP = "__key_up__#"; private static final String PREFIX_KEY_UP = "__key_up__#";
private static final Object[] NO_ARGUMENT = new Object[0];
private static ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>(); private static ConcurrentHashMap<Thread, Looper> sLoopers = new ConcurrentHashMap<>();
private AccessibilityBridge mAccessibilityBridge; private AccessibilityBridge mAccessibilityBridge;
private boolean mListeningKey = false;
private Handler mHandler; private Handler mHandler;
private Context mContext; private Context mContext;
private TouchObserver mTouchObserver; private TouchObserver mTouchObserver;
private long mLastTouchEventMillis; private long mLastTouchEventMillis;
private long mTouchEventTimeout = 10; private long mTouchEventTimeout = 10;
private boolean mListeningKey = false;
public Events(Context context, AccessibilityBridge accessibilityBridge) { public Events(Context context, AccessibilityBridge accessibilityBridge) {
mAccessibilityBridge = accessibilityBridge; mAccessibilityBridge = accessibilityBridge;
@@ -39,10 +40,19 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
} }
public void observeKey() { public void observeKey() {
ensureListeningKey(); if (mListeningKey)
return;
mListeningKey = true;
prepareLoopIfNeeded();
mAccessibilityBridge.ensureServiceEnabled();
AccessibilityService service = mAccessibilityBridge.getService();
if (service == null)
throw new ScriptStopException();
service.getOnKeyObserver().addListener(this);
} }
public void observeTouch() { public void observeTouch() {
prepareLoopIfNeeded();
if (mTouchObserver != null) if (mTouchObserver != null)
return; return;
mTouchObserver = new TouchObserver(mContext); mTouchObserver = new TouchObserver(mContext);
@@ -50,16 +60,19 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
mTouchObserver.observe(); mTouchObserver.observe();
} }
private void ensureListeningKey() { public void setTimeout(final Object listener, long t) {
if (mListeningKey) { prepareLoopIfNeeded();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
call(listener, NO_ARGUMENT);
}
}, t);
}
private void prepareLoopIfNeeded() {
if (Looper.myLooper() != null)
return; return;
}
mListeningKey = true;
mAccessibilityBridge.ensureServiceEnabled();
AccessibilityService service = mAccessibilityBridge.getService();
if (service == null)
throw new ScriptStopException();
service.getOnKeyObserver().addListener(this);
Looper.prepare(); Looper.prepare();
sLoopers.put(Thread.currentThread(), Looper.myLooper()); sLoopers.put(Thread.currentThread(), Looper.myLooper());
mHandler = new Handler(); mHandler = new Handler();
@@ -151,12 +164,17 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
} }
@Override @Override
public void onTouch(int x, int y) { public void onTouch(final int x, final int y) {
if (System.currentTimeMillis() - mLastTouchEventMillis < mTouchEventTimeout) { if (System.currentTimeMillis() - mLastTouchEventMillis < mTouchEventTimeout) {
return; return;
} }
mLastTouchEventMillis = System.currentTimeMillis(); mLastTouchEventMillis = System.currentTimeMillis();
emit("touch", x, y); mHandler.post(new Runnable() {
@Override
public void run() {
emit("touch", new Point(x, y));
}
});
} }
public static void removeThreadRecord(Thread thread) { public static void removeThreadRecord(Thread thread) {
@@ -170,5 +188,4 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
} }
} }
} }

View File

@@ -46,7 +46,7 @@ public class TouchObserver {
private class TouchEventObserver extends InputEventConverter { private class TouchEventObserver extends InputEventConverter {
private int mLastTouchX, mLastTouchY; private int mLastTouchX = -1, mLastTouchY = -1;
@Override @Override
public void convertEvent(@NonNull Event event) { public void convertEvent(@NonNull Event event) {