Auto.js学习笔记——快速入门:对控件的操作(常用函数、获取控件、点击、输入等)

基础知识

控件(Widget)

  • 控件(Widget)的概念类似于DOM中的元素对象
  • 手机屏幕上显示的整个页面就是由很多不同的控件组成的
    常见的控件:
    TextView 显示文字(“android.widget.TextView”)
    ImageView 显示图片(“android.widget.ImageView”)
    EditText 输入框
    Button 按钮,可附带图片
    CheckBox 复选框
  • 每个控件有其属性,例如:
    className 类名,表示控件类型(“android.widget.TextView”\等)
    packageName 包名,表示控件所在的应用包(“com.tencent.mobileqq”)
    clickable 控件是否可点击
    editable 控件是否可编辑
    longClickable 控件是否可长按
    bounds 控件在屏幕上的范围,当控件无法点击,用这个属性获取坐标
    checkable 控件是否可勾选
    checked 控件是否可已勾选
    scrollable 控件是否可滑动
    selected 控件是否已选择
    visibleToUser 控件是否可见
    enabled 控件是否已启用
    depth 控件的布局深度
    drawingOrder 控件在父控件的绘制顺序。
    indexInParent 控件在父控件的位置

使用Auto.js软件,在悬浮窗的“布局范围分析”中可以选择屏幕上的控件,并查看其各项属性的值

常用函数

以下介绍一些编写脚本时常用的代码,更多见Auto.js文档官方文档

  • sleep(n)暂停运行n毫秒,常见的情况是,软件的运行速度“跟不上”脚本,因此需要一定时间的等待(尤其是需要点击的控件以滑动的方式进入,若不等待可能点击不到)
  • toast(message)显示气泡信息
  • log(message)在控制台中输出信息
  • toastLog(message)上面两个函数的合体
  • exit()立即停止脚本运行

  • currentPackage()是当前正在运行的应用的包名
  • waitForPackage(package[, period = 200])等待指定的应用出现,period 轮询等待间隔(毫秒)
  • currentActivity()当前正在运行的Activity的名称
  • waitForActivity(activity[, period = 200])等待指定的Activity出现
  • waitFor()等待某物出现
    例如,代码第一句一般为auto.waitFor(),检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍界面,并等待无障碍服务启动
    又例如,要等待某个文本为“发送”的控件出现,代码为text("发送").waitFor();
  • exists()判断当前屏幕上是否存在某控件,如if(text("发送").exists())...

获取控件并操作

我们首先要①通过一定条件筛选出所需的控件②获取目标控件,③才能对其进行点击和编辑等操作(例如,要先获取到“确定”按钮的位置,才能控制脚本去点击它)

①筛选所需的控件:UiSelector选择器

我们使用UiSelector选择器筛选出所需要的控件,筛选的依据就是控件的属性
筛选时要保证条件可唯一确定某个控件,否则可能因为没有选择到所需的控件而无法实现期望的操作:

  • 通常用一个独一无二的属性来定位一个控件:这样的属性一般是idtextdesc
    例如用text("confirm").findOne().click()来点击一个按钮

在这个例子中, text("confirm")是选择器的条件(控件的text为"confirm"),findOne()表示基于这个条件找到一个控件,从而我们可以得到确认按钮,再执行click()即可点击"发送"按钮

  • 有时单靠一个属性无法定位(例如QQ中很多控件id相同),就需要通过链式调用来组合条件
    例如className("ImageView").depth(10).clickable(true).findOne().click()
function clickBtn(btnText,waitingDelay){//传入一个按钮,确保点击了该按钮(搭配findOne,可能传入null或按钮)
    var btn = text(btnText).clickable(true).findOne(waitingDelay);//在给定时间内持续寻找,直到找到
    if(!btn)return false;//未在给定时间内找到按钮
    while(!btn.click());//不断点击按钮直到成功,因此之前要确保按钮是可点击的
    return true;
}
function clickByCoord(btnText,waitingDelay){//控件本身无法点击,转而获取其坐标并模拟点击动作
	var btn = text(btnText).findOne(waitingDelay);//这里处理的是无法点击的控件
    if(!btn)return false;
    var coord= btn.bounds();
    while(!click(coord.centerX(), coord.centerY()));//click(x,y)
    return true;
}
UiSelector选择器:根据文本选择
  • text(str)选择出text属性等于字符串str的控件
  • textContains(str)
  • textStartsWith(prefix)
  • textEndsWith(suffix)
  • textMatches(reg)选出其text文本与正则表达式reg匹配的控件

正则表达式:
应用场景1:获取价格控件(¥ 1¥ 9.99等)
如果用JavaScript正则表达式(正则表达式是RegExp对象):
首尾用/.../括起来

var reg = new RegExp(/^¥\s\d+(\.\d+)?$/);
textMatches(reg).findOnce();
或直接
textMatches(/^¥\s\d+(\.\d+)?$/).findOnce();

如果用Java正则表达式(正则表达式是字符串):
首尾用"..."括起来
且在字符串内,需要使用\\来表达\

var reg = "^¥\\s\\d+(\\.\\d+)?$";
textMatches(reg).findOnce();

应用场景2:要要等待text为“发送”或“接收”或“确认xxx”的控件出现(三者之一均可)
则可以这样写:

textMatches(/(发送)|(接收)|(确认.*)/).waitFor();
UiSelector选择器:其他常用选择器
  • clickable([b = true])选择那些可以点击的控件,例如className("ImageView").clickable(true)className("ImageView").clickable()表示可以点击的图片控件
  • id(str):类似text(str),还有idContains(str)idStartsWith(prefix)idMatches(reg)
  • desc(str)同上
  • className(str)同上
  • boundsInside(left, top, right, buttom)boundsContains(left, top, right, buttom)bounds(left, top, right, buttom)基于坐标来选择控件,详见坐标篇
  • UiSelector.filter(f)为选择器附加自定义的过滤条件,其中f为一个函数,传入一个控件对象,返回true或false

②获取目标控件

直接在选择器后面加上findOne方法,就可以获取控件
例如

var w = id("action_log").findOne(6000);

if(w != null)
    w.click();//如果找到控件则点击
else
    toast("没有找到日志图标");//否则提示没有找到
获取控件的方法总结
  • UiSelector.findOne()查找满足条件的控件并返回,若找不到,函数会阻塞,直至所描述的控件出现为止(因此此函数不会返回null
  • UiSelector.findOne(timeout)同上,区别在于规定了查找控件的时间:如果超过timeout毫秒还未找到,则返回null
  • UiSelector.findOnce()相较于上面的持续搜索,此函数只在屏幕上搜索一次(而非不停地一直搜索)
  • UiSelector.findOnce(i)返回第 i 个符合条件的控件

上面的方法返回一个控件对象UiObject:只会搜索并返回第一个符合条件的控件(这里的控件次序,是搜索算法深度优先搜索DSF决定的)
如果要返回所有符合条件的控件集合UiCollection:使用下面的方法

  • UiSelector.find()返回 UiCollection。找出所有满足条件的控件并返回一个控件集合(这个搜索只进行一次,并不保证一定会找到,因而会出现返回的控件集合为空的情况)
  • UiSelector.untilFind()返回 UiCollection。同上,区别在于如果屏幕上一直没有出现满足条件的控件,则该函数会保持阻塞(函数永远不会返回空集合)

UiCollection实际上是一个UiObject控件的数组(继承了数组),因此可以使用数组的函数和属性,例如length属性、forEach函数,遍历时可以用传统的for遍历,也可用数组的forEach遍历,更多详见对控件的操作(控件集合UiCollection篇)

更多获取控件的方法

如果已经获取到某个控件,还可以根据该控件与其他控件之间的层级关系,获取其它控件(如获取控件的父控件、子控件等);也可以在该控件的子控件、孙控件…中寻找符合条件的控件
这部分内容详见后文:③操作和点击控件-对控件的操作:基于当前的控件获取其他控件

③操作和点击控件

成功获取一个控件对象,即UiObject后,就可以操作这个控件:可以通过获取到这个控件对象的属性,也可以对控件进行点击、长按等操作

注意,并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。例如对于某个自定义的类名为android.view.View的控件,clickable属性为false却能点击。

获取控件的属性
  • UiObject.text()获取控件的文本,如果控件没有文本,返回""
  • UiObject.id()获取控件的id,如果一个控件没有id,则返回null
  • UiObject.bounds()返回控件在屏幕上的范围,其值是一个Rect对象
  • 更多详见官方文档:UiObject

对控件的操作:点击、操作文本等

  • UiObject.click()点击该控件,并返回是否点击成功
  • UiObject.longClick()长按该控件
  • UiObject.scrollUp()UiObject.scrollLeft()UiObject.scrollForward()
  • 关于文本的操作,见后文“输入文本”部分

对控件的操作:基于当前的控件获取其他控件

实际上,页面控件对象的组织结构非常类似于DOM树,各控件之间都是有着层次结构的(可以获取一个节点的父节点、子节点等)

  • UiObject.children()返回 UiCollection。返回该控件的所有子控件组成的控件集合
  • UiObject.parent()返回一个控件对象 UiObject。返回该控件的父控件
  • UiObject.findOne(selector)选择器selector在该控件的子控件、孙控件…中搜索符合该选择器条件的控件,并返回找到的第一个控件
    例如var like = aWidget.findOne(id("feed_action_view_like"));
  • UiObject.find(selector)同上,在该控件的子控件、孙控件…中搜索,但返回的是符合条件的控件集合
  • UiObject.findByText(str)在当前控件的子控件,孙控件…中搜索其text或desc属性包含str字符串的控件,并返回它们的集合

各个控件之间的具体层次结构可以在Auto.js应用悬浮窗的"布局层次分析中"查看

对控件的操作:基于坐标的操作

有时获取一个控件比较困难,可以直接基于坐标来进行点击或拖动等操作

要获取要点击的位置的坐标,可以在开发者选项中开启"指针位置",也可直接结合Auto.js应用提供的“布局范围分析”中控件的bounds属性得到坐标值

  • click(x, y)模拟点击,时长约150ms,因此可能有连击速度过慢的问题,可以用press()代替
  • longClick(x, y)模拟长按
  • press(x, y, duration)模拟按住,duration为按住时长(单位ms)
    按住时长较短,被系统认为是点击;时长超过500毫秒,则被系统认为是长按
  • swipe(x1, y1, x2, y2, duration)模拟从坐标(x1, y1)滑动到(x2, y2),返回是否成功
  • gesture(duration, [x1, y1], [x2, y2], ...)模拟沿着一系列路径滑动
    gesture(1000, [0, 0], [500, 500], [500, 1000])
  • gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)模拟多个同时的手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势(可省略,默认为0);duration为执行时长;

更多基于坐标的操作,详见对控件的操作(坐标篇)

输入文本

配合剪切板实现输入:

  • setClip(text);
  • getClip()返回系统剪贴板内容
  • UiObject.paste()对输入框控件进行粘贴操作

根据传入的参数来输入文本:

  • setText([i, ]text)将第i 个输入框的文本设置为text;不加参数i,则把所有输入框的文本都置为text
  • input([i, ]text)在将第i 个输入框原来的文本上追加文本text,不加参数i则会把所有输入框的文本追加内容text

上面介绍的是全局函数,下面是一些基于控件的操作:

  • UiObject.setText(text)设置输入框控件的文本内容,只对可编辑的输入框(editable为true)有效
  • UiObject.setSelection(start, end)对输入框控件设置选中的文字内容
  • UiObject.copy()对输入框文本的选中内容进行复制,只能用于输入框控件,并且当前输入框控件有选中的文本(可以通过setSelection()函数来设置输入框选中的内容)
  • UiObject.cut()对输入框文本的选中内容进行剪切,后面同上
  • UiObject.paste()对输入框控件进行粘贴,粘贴剪贴板的内容
  • 32
    点赞
  • 281
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
好的,关于 Android 开关按钮的背景图和自定义控件,我可以为您提供一些学习笔记和分享。 1. Android 开关按钮背景图 在 Android 中,开关按钮的背景图可以通过 drawable 文件夹下的 xml 文件来实现。以下是一个简单的例子: ```xml <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/switch_on" android:state_checked="true"/> <item android:drawable="@drawable/switch_off"/> </selector> ``` 其中,我们使用了 selector 标签来表示按钮的状态。在 checked 为 true 时,使用 switch_on 图片作为背景图;否则使用 switch_off 图片作为背景图。 2. Android 自定义控件之开关按钮学习笔记分享 如果您想完全自定义一个开关按钮控件,以下是一些实现步骤: 1) 创建一个继承自 CompoundButton 的类,例如 SwitchButton。 2) 实现 SwitchButton 的构造函数和一些必要的属性。 ```java public class SwitchButton extends CompoundButton { public SwitchButton(Context context) { super(context); init(); } public SwitchButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { // 初始化一些属性 } } ``` 3) 在 init() 方法中,设置一些默认属性,例如背景图、文字等。 4) 重写 onMeasure() 方法,计算出 SwitchButton 的宽高。 ```java @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(widthSize, heightSize); } ``` 5) 重写 onDraw() 方法,绘制 SwitchButton 的背景图和文字。 ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制背景图和文字 } ``` 6) 重写 onTouchEvent() 方法,处理用户的触摸事件,例如改变 SwitchButton 的状态。 ```java @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 处理按下事件 break; case MotionEvent.ACTION_MOVE: // 处理移动事件 break; case MotionEvent.ACTION_UP: // 处理抬起事件 break; } return super.onTouchEvent(event); } ``` 7) 最后,将 SwitchButton 添加到布局文件中即可。 ```xml <com.example.myapp.SwitchButton android:id="@+id/switchButton" android:layout_width="wrap_content" android:layout_height="wrap_content"/> ``` 以上就是自定义开关按钮控件的一些步骤和注意事项。希望对您有帮助!
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值