UiObject

控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。 在QQ界面经常会出现多个id为"name"的控件,在微信上则每个版本的id都会变化。对于这些软件而言比较难用id定位控件。 ## UiSelector.idContains(str) * `str` {string} id要包含的字符串 为当前选择器附加控件"id包含字符串str"的筛选条件。比较少用。 ## UiSelector.idStartsWith(prefix) * `prefix` {string} id前缀 为当前选择器附加"id需要以prefix开头"的筛选条件。比较少用。 ## UiSelector.idEndsWith(suffix) * `suffix` {string} id后缀 为当前选择器附加"id需要以suffix结束"的筛选条件。比较少用。 ## UiSelector.idMatches(reg) * reg {Regex} | {string} id要满足的正则表达式 附加id需要满足正则表达式。 需要注意的是,如果正则表达式是字符串,则需要使用`\\`来表达`\`(也即Java正则表达式的形式),例如`textMatches("\\d+")`匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如`textMatches(/\d+/)`。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如`textMatches("/\\d+/")`的表达式,否则会被开头的"/"和结尾的"/"会被忽略。 ``` idMatches("[a-zA-Z]+") ``` ## UiSelector.className(str) * `str` {string} 控件文本 * 返回 {UiSelector} 返回选择器自身以便链式调用 为当前选择器附加控件"className等于字符串str"的筛选条件。 控件的className(类名)表示一个控件的类别,例如文本控件的类名为android.widget.TextView。 如果一个控件的类名以"android.widget."开头,则可以省略这部分,例如文本控件可以直接用`className("TextView")`的选择器。 常见控件的类名如下: * `android.widget.TextView` 文本控件 * `android.widget.ImageView` 图片控件 * `android.widget.Button` 按钮控件 * `android.widget.EditText` 输入框控件 * `android.widget.AbsListView` 列表控件 * `android.widget.LinearLayout` 线性布局 * `android.widget.FrameLayout` 帧布局 * `android.widget.RelativeLayout` 相对布局 * `android.widget.RelativeLayout` 相对布局 * `android.support.v7.widget.RecyclerView` 通常也是列表控件 ## UiSelector.classNameContains(str) * `str` {string} 要包含的字符串 为当前选择器附加控件"className需要包含字符串str"的筛选条件。 ## UiSelector.classNameStartsWith(prefix) * `prefix` {string} 前缀 为当前选择器附加控件"className需要以prefix开头"的筛选条件。 ## UiSelector.classNameEndsWith(suffix) * `suffix` {string} 后缀 为当前选择器附加控件"className需要以suffix结束"的筛选条件。 ## UiSelector.classNameMatches(reg) * `reg` {string} | {Regex} 要满足的正则表达式。 为当前选择器附加控件"className需要满足正则表达式reg"的条件。 有关正则表达式,可以查看[正则表达式 - 菜鸟教程](http://www.runoob.com/Stringp/Stringp-example.html)。 需要注意的是,如果正则表达式是字符串,则需要使用`\\`来表达`\`(也即Java正则表达式的形式),例如`textMatches("\\d+")`匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如`textMatches(/\d+/)`。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如`textMatches("/\\d+/")`的表达式,否则会被开头的"/"和结尾的"/"会被忽略。 ## UiSelector.packageName(str) * `str` {string} 控件文本 * 返回 {UiSelector} 返回选择器自身以便链式调用 为当前选择器附加控件"packageName等于字符串str"的筛选条件。 控件的packageName表示控件所属界面的应用包名。例如微信的包名为"com.tencent.mm", 那么微信界面的控件的packageName为"com.tencent.mm"。 要查看一个应用的包名,可以用函数`app.getPackageName()`获取,例如`toast(app.getPackageName("微信"))`。 ## UiSelector.packageNameContains(str) * `str` {string} 要包含的字符串 为当前选择器附加控件"packageName需要包含字符串str"的筛选条件。 ## UiSelector.packageNameStartsWith(prefix) * `prefix` {string} 前缀 为当前选择器附加控件"packageName需要以prefix开头"的筛选条件。 ## UiSelector.packageNameEndsWith(suffix) * `suffix` {string} 后缀 为当前选择器附加控件"packageName需要以suffix结束"的筛选条件。 ## UiSelector.packageNameMatches(reg) * `reg` {string} | {Regex} 要满足的正则表达式。 为当前选择器附加控件"packageName需要满足正则表达式reg"的条件。 有关正则表达式,可以查看[正则表达式 - 菜鸟教程](http://www.runoob.com/Stringp/Stringp-example.html)。 ## UiSelector.bounds(left, top, right, bottom) * `left` {number} 控件左边缘与屏幕左边的距离 * `top` {number} 控件上边缘与屏幕上边的距离 * `right` {number} 控件右边缘与屏幕左边的距离 * `bottom` {number} 控件下边缘与屏幕上边的距离 一个控件的bounds属性为这个控件在屏幕上显示的范围。我们可以用这个范围来定位这个控件。尽管用这个方法定位控件对于静态页面十分准确,却无法兼容不同分辨率的设备;同时对于列表页面等动态页面无法达到效果,因此使用不推荐该选择器。 注意参数的这四个数字不能随意填写,必须精确的填写控件的四个边界才能找到该控件。例如,要点击QQ主界面的右上角加号,我们用布局分析查看该控件的属性,如下图: 可以看到bounds属性为(951, 67, 1080, 196),此时使用代码`bounds(951, 67, 1080, 196).clickable().click()`即可点击该控件。 ## UiSelector.boundsInside(left, top, right, bottom) * `left` {number} 范围左边缘与屏幕左边的距离 * `top` {number} 范围上边缘与屏幕上边的距离 * `right` {number} 范围右边缘与屏幕左边的距离 * `bottom` {number} 范围下边缘与屏幕上边的距离 为当前选择器附加控件"bounds需要在left, top, right, bottom构成的范围里面"的条件。 这个条件用于限制选择器在某一个区域选择控件。例如要在屏幕上半部分寻找文本控件TextView,代码为: ``` var w = className("TextView").boundsInside(0, 0, device.width, device.height / 2).findOne(); log(w.text()); ``` 其中我们使用了`device.width`来获取屏幕宽度,`device.height`来获取屏幕高度。 ## UiSelector.boundsContains(left, top, right, bottom) * `left` {number} 范围左边缘与屏幕左边的距离 * `top` {number} 范围上边缘与屏幕上边的距离 * `right` {number} 范围右边缘与屏幕左边的距离 * `bottom` {number} 范围下边缘与屏幕上边的距离 为当前选择器附加控件"bounds需要包含left, top, right, bottom构成的范围"的条件。 这个条件用于限制控件的范围必须包含所给定的范围。例如给定一个点(500, 300), 寻找在这个点上的可点击控件的代码为: ``` var w = boundsContains(500, 300, 500, 300).clickable().findOne(); w.click(); ``` ## UiSelector.drawingOrder(order) * order {number} 控件在父视图中的绘制顺序 为当前选择器附加控件"drawingOrder等于order"的条件。 drawingOrder为一个控件在父控件中的绘制顺序,通常可以用于区分同一层次的控件。 但该属性在Android 7.0以上才能使用。 ## UiSelector.clickable([b = true]) * `b` {Boolean} 表示控件是否可点击 为当前选择器附加控件是否可点击的条件。但并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。对于自定义控件(例如显示类名为android.view.View的控件)很多的clickable属性都为false都却能点击。 需要注意的是,可以省略参数`b`而表示选择那些可以点击的控件,例如`className("ImageView").clickable()`表示可以点击的图片控件的条件,`className("ImageView").clickable(false)`表示不可点击的图片控件的条件。 ## UiSelector.longClickable([b = true]) * `b` {Boolean} 表示控件是否可长按 为当前选择器附加控件是否可长按的条件。 ## UiSelector.checkable([b = true]) * `b` {Boolean} 表示控件是否可勾选 为当前选择器附加控件是否可勾选的条件。勾选通常是对于勾选框而言的,例如图片多选时左上角通常有一个勾选框。 ## UiSelector.selected([b = true]) * `b` {Boolean} 表示控件是否被选 为当前选择器附加控件是否已选中的条件。被选中指的是,例如QQ聊天界面点击下方的"表情按钮"时,会出现自己收藏的表情,这时"表情按钮"便处于选中状态,其selected属性为true。 ## UiSelector.enabled([b = true]) * `b` {Boolean} 表示控件是否已启用 为当前选择器附加控件是否已启用的条件。大多数控件都是启用的状态(enabled为true),处于“禁用”状态通常是灰色并且不可点击。 ## UiSelector.scrollable([b = true]) * `b` {Boolean} 表示控件是否可滑动 为当前选择器附加控件是否可滑动的条件。滑动包括上下滑动和左右滑动。 可以用这个条件来寻找可滑动控件来滑动界面。例如滑动Auto.js的脚本列表的代码为: ``` className("android.support.v7.widget.RecyclerView").scrollable().findOne().scrollForward(); //或者classNameEndsWith("RecyclerView").scrollable().findOne().scrollForward(); ``` ## UiSelector.editable([b = true]) * `b` {Boolean} 表示控件是否可编辑 为当前选择器附加控件是否可编辑的条件。一般来说可编辑的控件为输入框(EditText),但不是所有的输入框(EditText)都可编辑。 ## UiSelector.multiLine([b = true]) * b {Boolean} 表示文本或输入框控件是否是多行显示的 为当前选择器附加控件是否文本或输入框控件是否是多行显示的条件。 ## UiSelector.findOne() * 返回 [UiObject](#widgets_based_automation_uiobject) 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件。如果找不到控件,当屏幕内容发生变化时会重新寻找,直至找到。 需要注意的是,如果屏幕上一直没有出现所描述的控件,则该函数会阻塞,直至所描述的控件出现为止。因此此函数不会返回`null`。 该函数本来应该命名为`untilFindOne()`,但由于历史遗留原因已经无法修改。如果想要只在屏幕上搜索一次而不是一直搜索,请使用`findOnce()`。 另外,如果屏幕上有多个满足条件的控件,`findOne()`采用深度优先搜索(DFS),会返回该搜索算法找到的第一个控件。注意控件找到的顺序有时会起到作用。 ## UiSelector.findOne(timeout) * `timeout` {number} 搜索的超时时间,单位毫秒 * 返回 [UiObject](#widgets_based_automation_uiobject) 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件;如果在timeout毫秒的时间内没有找到符合条件的控件,则终止搜索并返回`null`。 该函数类似于不加参数的`findOne()`,只不过加上了时间限制。 示例: ``` //启动Auto.js launchApp("Auto.js"); //在6秒内找出日志图标的控件 var w = id("action_log").findOne(6000); //如果找到控件则点击 if(w != null){ w.click(); }else{ //否则提示没有找到 toast("没有找到日志图标"); } ``` ## UiSelector.findOnce() * 返回 [UiObject](#widgets_based_automation_uiobject) 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,如果找到符合条件的控件则返回该控件;否则返回`null`。 ## UiSelector.findOnce(i) * `i` {number} 索引 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,并返回第 i + 1 个符合条件的控件;如果没有找到符合条件的控件,或者符合条件的控件个数 < i, 则返回`null`。 注意这里的控件次序,是搜索算法深度优先搜索(DSF)决定的。 ## UiSelector.find() * 返回 [UiCollection](#widgets_based_automation_uicollection) 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,找到所有满足条件的控件集合并返回。这个搜索只进行一次,并不保证一定会找到,因而会出现返回的控件集合为空的情况。 不同于`findOne()`或者`findOnce()`只找到一个控件并返回一个控件,`find()`函数会找出所有满足条件的控件并返回一个控件集合。之后可以对控件集合进行操作。 可以通过empty()函数判断找到的是否为空。例如: ``` var c = className("AbsListView").find(); if(c.empty()){ toast("找到啦"); }else{ toast("没找到╭(╯^╰)╮"); } ``` ## UiSelector.untilFind() * 返回 [UiCollection](#widgets_based_automation_uicollection) 根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到找到至少一个满足条件的控件为止,并返回所有满足条件的控件集合。 该函数与`find()`函数的区别在于,该函数永远不会返回空集合;但是,如果屏幕上一直没有出现满足条件的控件,则该函数会保持阻塞。 ## UiSelector.exists() * 返回 {Boolean} 判断屏幕上是否存在控件符合选择器所确定的条件。例如要判断某个文本出现就执行某个动作,可以用: ``` if(text("某个文本").exists()){ //要支持的动作 } ``` ## UiSelector.waitFor() 等待屏幕上出现符合条件的控件;在满足该条件的控件出现之前,该函数会一直保持阻塞。 例如要等待包含"哈哈哈"的文本控件出现的代码为: ``` textContains("哈哈哈").waitFor(); ``` ## UiSelector.filter(f) * `f` {Function} 过滤函数,参数为UiObject,返回值为boolean 为当前选择器附加自定义的过滤条件。 例如,要找出屏幕上所有文本长度为10的文本控件的代码为: ``` var uc = className("TextView").filter(function(w){ return w.text().length == 10; }); ``` # UiObject UiObject表示一个控件,可以通过这个对象获取到控件的属性,也可以对控件进行点击、长按等操作。 获取一个UiObject通常通过选择器的`findOne()`, `findOnce()`等函数,也可以通过UiCollection来获取,或者通过`UiObject.child()`, `UiObject.parent()`等函数来获取一个控件的子控件或父控件。 ## UiObject.click() * 返回 {Boolean} 点击该控件,并返回是否点击成功。 如果该函数返回false,可能是该控件不可点击(clickable为false),当前界面无法响应该点击等(这种情况下可以使用`clickCenter()`代替)。 ## UiObject.clickCenter() **[[Pro 8.8.17新增](https://pro.autojs.org/)]** * 返回 {Boolean} 使用坐标点击该控件的中点,相当于`click(uiObj.bounds().centerX(), uiObject.bounds().centerY())`。 返回是否点击成功。 ## UiObject.longClick() * 返回 {Boolean} 长按该控件,并返回是否点击成功。 如果该函数返回false,可能是该控件不可点击(longClickable为false),当前界面无法响应该点击等。 ## UiObject.setText(text) * `text` {string} 文本 * 返回 {Boolean} 设置输入框控件的文本内容,并返回是否设置成功。 该函数只对可编辑的输入框(editable为true)有效。 ## UiObject.copy() * 返回 {Boolean} 对输入框文本的选中内容进行复制,并返回是否操作成功。 该函数只能用于输入框控件,并且当前输入框控件有选中的文本。可以通过`setSelection()`函数来设置输入框选中的内容。 ``` var et = className("EditText").findOne(); //选中前两个字 et.setSelection(0, 2); //对选中内容进行复制 if(et.copy()){ toast("复制成功"); }else{ toast("复制失败"); } ``` ## UiObject.cut() 对输入框文本的选中内容进行剪切,并返回是否操作成功。 该函数只能用于输入框控件,并且当前输入框控件有选中的文本。可以通过`setSelection()`函数来设置输入框选中的内容。 ## UiObject.paste() * 返回 {Boolean} 对输入框控件进行粘贴操作,把剪贴板内容粘贴到输入框中,并返回是否操作成功。 ``` //设置剪贴板内容为“你好” setClip("你好"); var et = className("EditText").findOne(); et.paste(); ``` ## UiObject.setSelection(start, end) * `start` {number} 选中内容起始位置 * `end` {number} 选中内容结束位置(不包括) * 返回 {Boolean} 对输入框控件设置选中的文字内容,并返回是否操作成功。 索引是从0开始计算的;并且,选中内容不包含end位置的字符。例如,如果一个输入框内容为"123456789",要选中"4567"的文字的代码为`et.setSelection(3, 7)`。 该函数也可以用来设置光标位置,只要参数的end等于start,即可把输入框光标设置在start的位置。例如`et.setSelection(1, 1)`会把光标设置在第一个字符的后面。 ## UiObject.scrollForward() * 返回 {Boolean} 对控件执行向前滑动的操作,并返回是否操作成功。 向前滑动包括了向右和向下滑动。如果一个控件既可以向右滑动和向下滑动,那么执行`scrollForward()`的行为是未知的(这是因为Android文档没有指出这一点,同时也没有充分的测试可供参考)。 ## UiObject.scrollBackward() * 返回 {Boolean} 对控件执行向后滑动的操作,并返回是否操作成功。 向后滑动包括了向右和向下滑动。如果一个控件既可以向右滑动和向下滑动,那么执行`scrollForward()`的行为是未知的(这是因为Android文档没有指出这一点,同时也没有充分的测试可供参考)。 ## UiObject.select() * 返回 {Boolean} 对控件执行"选中"操作,并返回是否操作成功。"选中"和`isSelected()`的属性相关,但该操作十分少用。 ## UiObject.collapse() * 返回 {Boolean} 对控件执行折叠操作,并返回是否操作成功。 ## UiObject.expand() * 返回 {Boolean} 对控件执行操作,并返回是否操作成功。 ## UiObject.show() 对集合中所有控件执行显示操作,并返回是否全部操作成功。 ## UiObject.scrollUp() 对集合中所有控件执行向上滑的操作,并返回是否全部操作成功。 ## UiObject.scrollDown() 对集合中所有控件执行向下滑的操作,并返回是否全部操作成功。 ## UiObject.scrollLeft() 对集合中所有控件执行向左滑的操作,并返回是否全部操作成功。 ## UiObject.scrollRight() ## children() * 返回 [UiCollection](#widgets_based_automation_uicollection) 返回该控件的所有子控件组成的控件集合。可以用于遍历一个控件的子控件,例如: ``` className("AbsListView").findOne().children() .forEach(function(child){ log(child.className()); }); ``` ## childCount() * 返回 {number} 返回子控件数目。 ## child(i) * i {number} 子控件索引 * 返回 {UiObject} 返回第i+1个子控件。如果i>=控件数目或者小于0,则抛出异常。 需要注意的是,由于布局捕捉的问题,该函数可能返回`null`,也就是可能获取不到某个子控件。 遍历子控件的示例: ``` var list = className("AbsListView").findOne(); for(var i = 0; i < list.childCount(); i++){ var child = list.child(i); log(child.className()); } ``` ## parent() * 返回 {UiObject} 返回该控件的父控件。如果该控件没有父控件,返回`null`。 ## bounds() * 返回 [Rect](https://hyb1996.github.io/AutoJs-Docs/widgets-based-automation.html#widgets_based_automation_rect) 返回控件在屏幕上的范围,其值是一个[Rect](https://hyb1996.github.io/AutoJs-Docs/widgets-based-automation.html#widgets_based_automation_rect)对象。 示例: ``` var b = text("Auto.js").findOne().bounds(); toast("控件在屏幕上的范围为" + b); ``` 如果一个控件本身无法通过`click()`点击,那么我们可以利用`bounds()`函数获取其坐标,再利用坐标点击。例如: ``` var b = desc("打开侧拉菜单").findOne().bounds(); click(b.centerX(), b.centerY()); //如果使用root权限,则用 Tap(b.centerX(), b.centerY()); ``` ## boundsInParent() * 返回 [Rect](https://hyb1996.github.io/AutoJs-Docs/widgets-based-automation.html#widgets_based_automation_rect) 返回控件在父控件中的范围,其值是一个[Rect](https://hyb1996.github.io/AutoJs-Docs/widgets-based-automation.html#widgets_based_automation_rect)对象。 ## drawingOrder() * 返回 {number} 返回控件在父控件中的绘制次序。该函数在安卓7.0及以上才有效,7.0以下版本调用会返回0。 ## id() * 返回 {string} 获取控件的id,如果一个控件没有id,则返回`null`。 ## text() * 返回 {string} 获取控件的文本,如果控件没有文本,返回`""`。 ## findByText(str) * `str` {string} 文本 * 返回 [UiCollection](#widgets_based_automation_uicollection) 根据文本text在子控件中递归地寻找并返回文本或描述(desc)**包含**这段文本str的控件,返回它们组成的集合。 该函数会在当前控件的子控件,孙控件,曾孙控件...中搜索text或desc包含str的控件,并返回它们组合的集合。 ## findOne(selector) * `selector` [UiSelector](#widgets_based_automation_uiselector) * 返回 [UiObject](#widgets_based_automation_uiobject) 根据选择器selector在该控件的子控件、孙控件...中搜索符合该选择器条件的控件,并返回找到的第一个控件;如果没有找到符合条件的控件则返回`null`。 例如,对于酷安动态列表,我们可以遍历他的子控件(每个动态列表项),并在每个子控件中依次寻找点赞数量和图标,对于点赞数量小于10的点赞: ``` //找出动态列表 var list = id("recycler_view").findOne(); //遍历动态 list.children().forEach(function(child){ //找出点赞图标 var like = child.findOne(id("feed_action_view_like")); //找出点赞数量 var likeCount = child.findOne(id("text_view")); //如果这两个控件没有找到就不继续了 if(like == null || likeCount == null){ return; } //判断点赞数量是否小于10 if(parseInt(likeCount.text()) < 10){ //点赞 like.click(); } }); ``` ## find(selector) * `selector` [UiSelector](#widgets_based_automation_uiselector) * 返回 [UiCollection](#widgets_based_automation_uicollection) 根据选择器selector在该控件的子控件、孙控件...中搜索符合该选择器条件的控件,并返回它们组合的集合。 # UiCollection UiCollection, 控件集合, 通过选择器的`find()`, `untilFind()`方法返回的对象。 UiCollection"继承"于数组,实际上是一个UiObject的数组,因此可以使用数组的函数和属性,例如使用length属性获取UiCollection的大小,使用forEach函数来遍历UiCollection。 例如,采用forEach遍历屏幕上所有的文本控件并打印出文本内容的代码为: ``` console.show(); className("TextView").find().forEach(function(tv){ if(tv.text() != ""){ log(tv.text()); } }); ``` 也可以使用传统的数组遍历方式: ``` console.show(); var uc = className("TextView").find(); for(var i = 0; i < uc.length; i++){ var tv = uc[i]; if(tv.text() != ""){ log(tv.text()); } } ``` UiCollection的每一个元素都是UiObject,我们可以取出他的元素进行操作,例如取出第一个UiObject并点击的代码为`ui[0].click()`。如果想要对该集合的所有元素进行操作,可以直接在集合上调用相应的函数,例如`uc.click()`,该代码会对集合上所有UiObject执行点击操作并返回是否全部点击成功。 因此,UiCollection具有所有UiObject对控件操作的函数,包括`click()`, `longClick()`, `scrollForward()`等等,不再赘述。 ## UiCollection.size() * 返回 {number} 返回集合中的控件数。 历史遗留函数,相当于属性length。 ## UiCollection.get(i) * `i` {number} 索引 * 返回 [UiObject](#widgets_based_automation_uiobject) 返回集合中第i+1个控件(UiObject)。 历史遗留函数,建议直接使用数组下标的方式访问元素。 ## UiCollection.each(func) * `func` {Function} 遍历函数,参数为UiObject。 遍历集合。 历史遗留函数,相当于`forEach`。参考[forEach](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)。 ## empty() * 返回 {Boolean} 返回控件集合是否为空。 ## nonEmpty() * 返回 {Boolean} 返回控件集合是否非空。 ## UiCollection.find(selector) * `selector` [UiSelector](#widgets_based_automation_uiselector) * 返回 [UiCollection](#widgets_based_automation_uicollection) 根据selector所确定的条件在该控件集合的控件、子控件、孙控件...中找到所有符合条件的控件并返回找到的控件集合。 注意这会递归地遍历控件集合里所有的控件以及他们的子控件。和数组的`filter`函数不同。 例如: ``` var names = id("name").find(); //在集合 var clickableNames = names.find(clickable()); ``` ## UiCollection.findOne(selector) * `selector` [UiSelector](#widgets_based_automation_uiselector) * 返回 [UiObject](#widgets_based_automation_uiobject) 根据选择器selector在该控件集合的控件的子控件、孙控件...中搜索符合该选择器条件的控件,并返回找到的第一个控件;如果没有找到符合条件的控件则返回`null`。