Auto.js学习笔记——快速入门:对控件的操作(常用函数、获取控件、点击、输入等)
function clickBtn(btnText,waitingDelay){//传入一个按钮,确保点击了该按钮(搭配findOne,可能传入null或按钮)var btn = text(btnText).clickable(true).findOne(waitingDelay);//在给定时间内持续寻找,直到找到if(!btn)return false;//未在给定时间内找到按钮while(!
基础知识
控件(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选择器筛选出所需要的控件,筛选的依据就是控件的属性
筛选时要保证条件可唯一确定某个控件,否则可能因为没有选择到所需的控件而无法实现期望的操作:
- 通常用一个独一无二的属性来定位一个控件:这样的属性一般是
id
、text
、desc
等
例如用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,则返回nullUiObject.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,则把所有输入框的文本都置为textinput([i, ]text)
在将第i 个输入框原来的文本上追加文本text,不加参数i则会把所有输入框的文本追加内容text
上面介绍的是全局函数,下面是一些基于控件的操作:
UiObject.setText(text)
设置输入框控件的文本内容,只对可编辑的输入框(editable为true)有效UiObject.setSelection(start, end)
对输入框控件设置选中的文字内容UiObject.copy()
对输入框文本的选中内容进行复制,只能用于输入框控件,并且当前输入框控件有选中的文本(可以通过setSelection()
函数来设置输入框选中的内容)UiObject.cut()
对输入框文本的选中内容进行剪切,后面同上UiObject.paste()
对输入框控件进行粘贴,粘贴剪贴板的内容
更多推荐
所有评论(0)