参考

打造专属 uiautomatorviewer
由 uiautomator 二次开发得到的启发以及完善
uiautomatorviewer 二次开发之自动生成控件定位符

成果

> PS  源码是@xuxu 分享的,对比了其他几位前辈的,貌似缺了几个文件和图标,但没什么太大影响
另外给大伙贴个uiautomatorviewer的源码:
https://android.googlesource.com/platform/frameworks/testing/+/aecdc4a/uiautomator/utils/uiautomatorviewer/src/com/android/uiautomator

需要导入的依赖包在eclipse/plugins
    org.eclipse.core.commands_XXXXXX.jar
    org.eclipse.equinox.common_XXXXXXX.jar
    org.eclipse.jface_XXXXXXXX.jar
    org.eclipse.swt.win32.win32.x86_64_XXXXXX.jar

### 功能点
- 新增清除操作按钮
![](/photo/2016/bcb90d382f627cddd40574ba5c1512b5.png)
- Activity & xpth属性
![](/photo/2016/f541e7493d679a2facf1b646fe96b618.png)
- 右键菜单
 - Click
 - Sendkey(根据输入值,自动生成Sendkey脚本语言)
 - findElementBy (输入id或者class,返回符合要求的控件坐标。。。本来想标红的,无奈一直不成功)
 - 鼠标点击事件
 - sleep(根据输入值,自动生成sleep脚本语言)
 - 输入字符到输入框(仍有bug,adb无法输入中文 && 手机输入法影响)
![](/photo/2016/e84aebec2a3c14cad07090c86c936d1b.png)
![](/photo/2016/1e2c27da6a3ffab03db2143632e0c89d.png)
![](/photo/2016/b2bd71fc4d53739a6d55b0359d962178.png)
![](/photo/2016/9526352ff5fe283cc18b0064a19f1220.png)

- 扩展展示界面(显示内容过多时,点击清除操作按钮后清除显示的内容)
![](/photo/2016/0029f4f4c53e88b878e5ec24d9603531.png)

### 其他
这些扩展功能,参考里面的前辈基本都已经说过了,我在做的时候花的时间也主要是SWT上,这也只是我之前从未接触过Java图形编程的原因,查文档花的时间比较多,所以也就不赘述了。
所以讲下 [打造专属 uiautomatorviewer](https://testerhome.com/topics/4614) 中,@zengjunzhou 前辈提到的
> 控件的id或text或content-desc或class相同,能不能区分选中的控件是第几个?

- 简单思路:
 - 获取父节点和选中的节点
 - 获取父节点下一级子节点
 - 遍历子节点,对选中的节点左侧的子节点进行递归遍历,把结果并写入List

下面是我代码实现部分
#### 获取子节点
```java
/**
     * 返回需要的节点数组
     * @param parentNode 父节点
     * @param selectedNode 当前选中的节点
     * @return
     */
    public static List<BasicTreeNode> AllChildNodes(BasicTreeNode parentNode, BasicTreeNode selectedNode){
        //某个父节点下的所有子节点
        List<BasicTreeNode> childNodes = new ArrayList<BasicTreeNode>();
        Recursion(parentNode, selectedNode, childNodes);

        return childNodes;
    }

    /**
     * 简单的一个递归获取需要的子节点
     * @param currentNode 父节点
     * @param selectedNode 当前选中的节点
     * @param childList 存储的子节点数组
     */
    public static void Recursion(BasicTreeNode currentNode, BasicTreeNode selectedNode, List<BasicTreeNode> childList){
        if (currentNode.hasChild()) {
            for (BasicTreeNode temp : currentNode.getChildren()) {
                if (!temp.equals(selectedNode)) {
                    childList.add(temp);
                    if (temp.hasChild()) {
                        Recursion(temp, selectedNode, childList);
                    }
                    else {
                        continue;
                    }
                }
                else {
                    break;
                }
            }
        }
    }

调用

//class
                    MenuItem classInputItem = new MenuItem(inputChridItem, SWT.PUSH);
                    classInputItem.setText("class");
                    classInputItem.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e){
                            UiNode sele = (UiNode) UiAutomatorModel.getModel().getSelectedNode();
                            String classSele = sele.getAttribute("class");
                            InputDialog dialog = new InputDialog(getShell(), "请输入文本", "请输入", null, null);
                            String value = "";
                            if (dialog.open() == InputDialog.OK) {
                                value = dialog.getValue();
//                              System.out.println(value);
                                String ursClass = "driver.findElementById(\"" + classSele + "\").sendKeys(\"" + value + "\");";
                                System.out.println(ursClass);
                            }
                            int num = 0;
                            boolean flag = true;
                            BasicTreeNode parent = UiAutomatorModel.getModel().getSelectedNode().getParent();

                            List<BasicTreeNode> childNodes = BasicTreeNode.AllChildNodes(parent, UiAutomatorModel.getModel().getSelectedNode());

                            for (int i = 0; i < childNodes.size(); i++) {
                                BasicTreeNode temp = childNodes.get(i);
                                UiNode tempUinode = (UiNode) temp;

                                if (tempUinode.getAttribute("class").equals(classSele)) {
                                    num++;
                                    flag = false;
                                }

                            }

                            if (flag) {
                                String ursClass = "driver.findElementByClassName(\"" + classSele + "\").sendKeys(\"" + value + "\");" + "\n";
                                System.out.println(ursClass);
                                show += ursClass;
                                text.setText(show);
                            }
                            else {
                                String ursClasses = "driver.findElementsByClassName(\"" + classSele + "\").get(" + num + "\").sendKeys(\"" + value + "\");" + "\n";
                                System.out.println(ursClasses);
                                show += ursClasses;
                                text.setText(show);
                            }
                        }
            });


↙↙↙阅读原文可查看相关链接,并与作者交流