节点操作
## 快速使用
### 使用步骤
**1.打开手机助手**
**2.选择连接的手机**

**3.点击节点面板**

**4.在手机投屏界面,点击需要获取节点的范围**

**5.复制相关代码(选中后Ctrl+C)**

**6.运行代码,测试是否成功点击**

### 小技巧
搜索框中输入文字,回车即可快速定位想要的节点哦~

## 节点原理
观测手机助手生成的点击节点代码:
~~~
click clazz:'android.widget.TextView',text:'工程',res:'',desc:'',timeout:1001
~~~
可以发现,click方法通过clazz、text、res、desc属性来查询并且点击一个节点,JsDroid运行该代码后,会先获取系统界面的所有节点,通过匹配所有节点的属性,获取到我们需要的节点,进而获取它的范围,进行模拟点击操作。
## 节点属性
将手机助手的属性表展开

可以查看所有的属性名字以及属性内容。
## 节点属性表
| 属性名 | 属性说明 |
| --- | --- |
| index | 节点序号 |
| depth| 节点深度 |
| res | 节点资源id |
| text | 节点文字 |
| desc | 节点无障碍文字 |
| pkg | 节点所属包名 |
| clazz | 节点类名 |
| rect | 节点范围 |
| checkable | 节点是否可以选中 |
| checked | 节点是否已经选中 |
| clickable | 节点是否可以点击 |
| enable | 节点是否可用 |
| focusable | 节点是否可以聚焦 |
| focused | 节点是否聚焦 |
| longClickable | 节点是否可以长按 |
| scrollable | 节点是否可以滑动 |
| selected | 节点是否选择 |
| password | 节点是否为密码 |
## 通过By搜索节点
### **单属性搜索**
最简单的使用,就是查询界面的文字,如下所示:
~~~
import com.jsdroid.uiautomator2.By
def node = device.findObject(By.text(“工程“))
if (node){
node.click()
}
~~~
### **多属性搜索**
复杂一些的,需要组合多个属性查询,如下所示:
~~~
import com.jsdroid.uiautomator2.By
def node = device.findObject(By.text(“工程“).clazz(~/.*TextView/))
if (node){
node.click()
}
~~~
注意,By后面可以接多个属性值,By.text().clazz().depth()...,每个属性值都是用括号拼接,如果属性值是字符串类型的,可以用正则表达式进行模糊匹配,格式如上面代码中的“~/.*TextView/“。
### **搜索多个结果**
我们也可以搜索多个结果,得到结果集,如下所示:
~~~
import com.jsdroid.uiautomator2.By
//匹配文字节点
def by = By.clazz(~/.*TextView/)
def nodes = device.findObjects(by)
if (nodes){
//将结果集的文字输出
for(def node:nodes){
print node.text
}
}
~~~
## 通过Map点击节点
观测手机助手生成的点击节点代码:
~~~
click clazz:'android.widget.TextView',text:'工程',res:'',desc:'',timeout:1001
~~~
其实可以将上述代码进行拆分,得到下面的形式:
~~~
def map = [clazz:'android.widget.TextView',text:'工程',res:'',desc:'',timeout:1001]
click(map)
~~~
这种方式就是map搜索节点了,我们可以再次修改,加入正则表达式:
~~~
def map = [clazz:~/.*TextView/,text:'工程',res:'',desc:'',timeout:1001]
click(map)
~~~
合并:
~~~
click( [clazz:~/.*TextView/,text:'工程',res:'',desc:'',timeout:1001])
~~~
简写:
~~~
click clazz:~/.*TextView/,text:'工程',res:'',desc:'',timeout:1001
~~~
注意:上面的timeout指的是在1001毫秒内如果出现匹配的节点,则进行点击,总耗时是小于等于1001毫秒的,精确的说,是小于等于1001毫秒+程序执行时间。
## 通过Map搜索节点
将上述的点击节点代码改成findNode即可,如下:
~~~
def node = findNode( clazz:'android.widget.TextView',text:'工程',res:'',desc:'',timeout:1001)
if(node){
node.click()
}
~~~
也可以查询多个,如下:
~~~
def nodes = findNodes( clazz:'android.widget.TextView')
if(nodes){
for(def node : nodes){
print node.text
}
}
~~~
## 节点方法
节点查询后,可能我们并不仅仅只是点击,我们还需要获取节点的属性,这就需要调用节点的方法来获取它们,例如:
~~~
def node = findNode( clazz:'android.widget.TextView',text:'工程',timeout:1001)
if(node){
//输出节点的文字
print(node.text)
//输出节点的范围
print(node.visibleBounds)
}
~~~
这些方法到底在哪找到它们呢?我们可以按住Ctrl,然后鼠标点击上面代码中的visibleBounds,如下图所示:

跳转过去后,可以发现,它的代码为:

上下滚动,可以发现其它代码:

如果我们有点英语水平,就可以快速使用所有方法了,而如果我们没有英语水平,我们可以通过翻译工具进行翻译,例如:

可以知道,getResourceName()方法的用途是获取资源名,可以调用它:
~~~
def node = findNode( clazz:'android.widget.TextView',text:'工程',timeout:1001)
if(node){
print(node.getResourceName())
}
~~~
如果方法中带有get开头,并且具有返回值,我们可以简写它:
~~~
def node = findNode( clazz:'android.widget.TextView',text:'工程',timeout:1001)
if(node){
print(node.resourceName)
}
~~~