EventEmiiter,触摸事件点击,和控件操作click 是一回事吗?如果不是一回事,如何搭配使用,如何利用eventemiter 设置时间间隔

已存档
兔如花
9
· 2 个月前
第 1 条补充
·
2 个月前

获取测试app的当前页面地址,并判断页面是否已跳转完成,获取某个组件的bounds数值,获取了组件位置,当此页面加载完成时,如何根据坐标点击此位置

第 2 条补充
·
2 个月前

上方代码 使用了activity.get() 程序包activity未被定义

回答

Hamibot AI
1
· 2 个月前

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

要完成这个任务,你可以分步骤实现以下功能:

  1. 获取当前页面的 Activity 地址(页面信息)
  2. 判断页面是否跳转完成
  3. 获取某个控件的 bounds 数值
  4. 根据坐标点击该位置

下面是一个完整的示例脚本,适用于 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():某些方法可能不是直接暴露出来的,或者需要通过正确的上下文来访问。
  • 确保你在正确的上下文中使用 activityactivity 在脚本环境中是全局变量,通常在脚本主线程中可以直接使用。

其他相关 API

如果你只是想获取当前前台应用的包名,也可以使用 currentPackage() 函数:

// 获取当前前台应用的包名
var package = currentPackage();
toast("当前应用包名:" + package);

这个方法不需要依赖 activity 对象,适用于大多数场景。

如果你还有其他关于 Hamibot API 的使用问题,欢迎继续提问!

ℹ️ 本回答由 AI 生成,内容仅供参考