EventEmiiter,触摸事件点击,和控件操作click 是一回事吗?如果不是一回事,如何搭配使用,如何利用eventemiter 设置时间间隔
第 1 条补充
· 2 个月前
获取测试app的当前页面地址,并判断页面是否已跳转完成,获取某个组件的bounds数值,获取了组件位置,当此页面加载完成时,如何根据坐标点击此位置
第 2 条补充
· 2 个月前
上方代码 使用了activity.get() 程序包activity未被定义
回答
EventEmitter 和控件操作 click
不是一回事,它们的作用和使用场景不同。
1. EventEmitter
作用:
EventEmitter
是用于事件监听的机制。它允许你注册监听器,当特定事件发生时(如触摸、按键等),这些监听器会被调用。- 例如,你可以通过
events.onTouch(listener)
监听屏幕上的触摸事件,并获取触摸点的坐标。
使用场景:
- 当你需要对系统级事件(如触摸、按键)做出反应时,使用
EventEmitter
。 - 它适用于全局监听,而不是针对某个具体控件的操作。
示例:
// 启用触摸监听
events.observeTouch();
// 注册触摸监听器
events.onTouch(function (p) {
log(p.x + ', ' + p.y);
});
2. 控件操作 click
作用:
click
是控件的一种方法,用于模拟点击某个具体的 UI 元素(如按钮)。- 它通常与悬浮窗或页面中的控件绑定,直接触发控件的行为。
使用场景:
- 当你需要与特定的 UI 控件交互时(如点击“开始”按钮),使用
click
。 - 它适用于局部操作,而不是全局事件监听。
示例:
// 创建悬浮窗
var floatyWin = floaty.window(
<vertical>
<button id="startBtn" text="开始"/>
</vertical>
);
// 按钮点击事件监听
floatyWin.startBtn.click(function () {
toast('开始执行');
});
3. 如何搭配使用?
如果你需要结合 EventEmitter
和控件操作 click
,可以考虑以下方式:
- 监听全局触摸事件,并在某些条件下触发控件的点击行为。
示例:
// 启用触摸监听
events.observeTouch();
// 注册触摸监听器
events.onTouch(function (p) {
// 如果触摸点在某个控件的区域内
if (isInRegion(p, floatyWin.startBtn)) {
floatyWin.startBtn.click(); // 触发控件的点击行为
}
});
// 判断点是否在控件区域内
function isInRegion(point, view) {
return point.x >= view.left && point.x <= view.right &&
point.y >= view.top && point.y <= view.bottom;
}
4. 如何利用 EventEmitter
设置时间间隔?
EventEmitter
本身不提供设置时间间隔的功能,但你可以通过 events.setTouchEventTimeout(timeout)
来控制触摸事件的分发频率。
作用:
- 设置两个触摸事件之间的最小时间间隔,避免短时间内大量事件被触发。
示例:
// 设置触摸事件的最小时间间隔为 100 毫秒
events.setTouchEventTimeout(100);
// 启用触摸监听
events.observeTouch();
// 注册触摸监听器
events.onTouch(function (p) {
log("触摸点: " + p.x + ", " + p.y);
});
总结
EventEmitter
是用于监听全局事件(如触摸、按键)的机制,而click
是控件的局部操作。- 两者可以结合使用,比如在触摸事件中判断点击区域并触发控件的点击行为。
events.setTouchEventTimeout(timeout)
可以用来控制触摸事件的分发频率,避免事件拥堵。
补充回答 1
要完成这个任务,你可以分步骤实现以下功能:
- 获取当前页面的 Activity 地址(页面信息)
- 判断页面是否跳转完成
- 获取某个控件的 bounds 数值
- 根据坐标点击该位置
下面是一个完整的示例脚本,适用于 Hamibot 环境,使用 JavaScript 编写:
// 文档地址 https://docs.hamibot.com/
// 设置屏幕分辨率适配(根据你开发时的设备设置)
setScreenMetrics(1080, 1920);
// 获取当前应用的包名和 activity 名
function getCurrentActivity() {
var currentApp = app.getAppName(currentPackage());
var currentActivity = activity.get();
log("当前应用: " + currentApp);
log("当前页面: " + currentActivity);
return currentActivity;
}
// 判断页面是否跳转完成(简单方式:等待指定页面出现)
function waitForPage(pageName, timeout) {
timeout = timeout || 5000; // 默认超时时间 5 秒
var startTime = new Date().getTime();
while (true) {
if (activity.get() === pageName) {
log("已跳转到目标页面:" + pageName);
return true;
}
if (new Date().getTime() - startTime > timeout) {
log("等待页面超时:" + pageName);
return false;
}
sleep(200);
}
}
// 获取某个控件的 bounds 数值(例如通过 text 查找)
function getBoundsByText(textValue) {
var widget = text(textValue).findOne(3000); // 等待最多 3 秒
if (!widget) {
log("未找到文本为 " + textValue + " 的控件");
return null;
}
var bounds = widget.bounds();
log("找到控件位置:" + bounds.left + "," + bounds.top + " - " + bounds.right + "," + bounds.bottom);
return bounds;
}
// 使用 Tap 点击某个坐标(需要 root 权限)
function clickByBounds(bounds) {
if (!bounds) {
log("无效的 bounds 值");
return;
}
var x = bounds.centerX();
var y = bounds.centerY();
log("正在点击坐标:" + x + ", " + y);
Tap(x, y);
sleep(500); // 根据实际情况调整延时
}
// 主流程
var targetPage = "com.example.app.MainActivity"; // 替换为目标页面名称
var targetText = "立即购买"; // 替换为你要点击的控件文本
// 1. 获取当前页面
getCurrentActivity();
// 2. 等待页面加载完成
if (!waitForPage(targetPage)) {
toast("页面未加载完成");
exit();
}
// 3. 获取控件位置
var bounds = getBoundsByText(targetText);
if (!bounds) {
toast("未找到控件");
exit();
}
// 4. 点击控件中心位置
clickByBounds(bounds);
toast("操作完成");
脚本说明:
getCurrentActivity()
:获取当前应用和页面信息。waitForPage(pageName)
:轮询检测是否跳转到了目标页面。getBoundsByText(textValue)
:查找具有特定文本的控件并获取其bounds
。clickByBounds(bounds)
:通过Tap(x, y)
根据控件的中心坐标进行点击。
注意事项:
- 如果你的设备没有 Root 权限,可以将
Tap(x, y)
替换为click(x, y)
,但某些情况下可能无法点击非可点击控件。 - 控件加载可能有延迟,建议适当增加
sleep()
或使用findOne(timeout)
等待控件出现。 setScreenMetrics()
是为了适配不同分辨率设备,请根据你开发时使用的设备填写正确的宽高。
补充回答 2
出现“程序包activity未被定义”的错误通常是因为你使用了不正确的上下文或对象来调用 get()
方法。在 Hamibot 的 API 中,activity
是一个全局变量,代表当前的 Activity 上下文。
正确使用方式
你可以通过以下方式正确使用 activity
:
// 获取当前 Activity 的上下文
var currentActivity = activity;
toast(currentActivity.getPackageName());
示例:获取当前应用的包名
// 文档地址 https://docs.hamibot.com/
var currentActivity = activity;
toast("当前应用包名:" + currentActivity.getPackageName());
常见问题
- 不要直接写
activity.get()
:某些方法可能不是直接暴露出来的,或者需要通过正确的上下文来访问。 - 确保你在正确的上下文中使用
activity
:activity
在脚本环境中是全局变量,通常在脚本主线程中可以直接使用。
其他相关 API
如果你只是想获取当前前台应用的包名,也可以使用 currentPackage()
函数:
// 获取当前前台应用的包名
var package = currentPackage();
toast("当前应用包名:" + package);
这个方法不需要依赖 activity
对象,适用于大多数场景。
如果你还有其他关于 Hamibot API 的使用问题,欢迎继续提问!
ℹ️ 本回答由 AI 生成,内容仅供参考