autojs自己写布局分析(三)

829 阅读2分钟

牙叔教程 简单易懂

之前的两个教程:

一个写了绘制绿框,

一个写了查看控件信息,

今天我们来写 在布局层次中查看

UI构成

  • 全屏悬浮窗
  • recyclerView
  • 选中的view的classname显示为红色, 相关的父子级也显示为红色
  • 选中的view在屏幕中用红色矩形绘制出来

数据特征

  • 控件信息显示有顺序性
  • 控件是有状态的, 展开或者折叠
  • 控件是有层级的, 一层一层的

要展示那些数据

只展示必要的数据, 那些数据是必要的?

根节点是必要的, 以及与选中的节点相关的父子层级的节点

解析节点数据

之前的教程, 绘制绿框, 我们使用的是广度搜索, 这个教程呢?

因为这个列表是从上往下, 前面显示完所有的子孙后代的控件,

然后再显示之后的层级控件,

因此, 这里我们使用 深度搜索 Depth First Search

虽然说我们只在UI显示必要的数据, 但是在UI之后的数据, 必定要是完整的数据, 不然你的数据去哪里拿呢?

遍历节点

依然是从根节点开始

let windowRoot = auto.rootInActiveWindow;
log(windowRoot);

深度搜索 Depth First Search

这是DFS方式的递归, 通常递归都是dfs

function findViewNodesByDFS(viewNode) {
    let viewNodes = [];
    // 节点入库
    viewNodes.push(viewNode);
    // 遍历节点
    let childCount = viewNode.childCount();
    for (let i = 0; i < childCount; i++) {
        let childViewNode = viewNode.child(i);
        let childViewNodes = findViewNodesByDFS(childViewNode);
        viewNodes = viewNodes.concat(childViewNodes);
    }
    return viewNodes;
}

这个数据够吗?

不够, 只有节点信息, 没有节点状态, 也没有节点的层级信息;

节点的状态是展开还是折叠, 这个我们要知道;

节点在第几层, 我们也要知道;

所以, 在遍历节点的时候, 我们要把状态和层级也加上去

function findViewNodesByDFS(viewNode, parentViewNodeObj, childViewNodeIndex) {
    let viewNodeObjs = [];
    let viewNodeObj = null;
    if (!parentViewNodeObj) {
        // 处理根节点
        viewNodeObj = {
            viewNode: viewNode,
            _level: 0,
            _levelStr: "0",
            _expand: false,
        };
        viewNodeObjs.push(viewNodeObj);
    } else {
        // 其他节点
        viewNodeObj = {
            viewNode: viewNode,
            _level: parentViewNodeObj._level + 1,
            _levelStr: parentViewNodeObj._levelStr + "-" + childViewNodeIndex,
            _expand: false,
        };
        viewNodeObjs.push(viewNodeObj);
    }
    let childCount = viewNode.childCount();
    for (let i = 0; i < childCount; i++) {
        let childViewNode = viewNode.child(i);
        let childViewNodes = findViewNodesByDFS(childViewNode, viewNodeObj, i);
        viewNodeObjs = viewNodeObjs.concat(childViewNodes);
    }
    return viewNodeObjs;
}

在上面这个代码中, 我们增加了三个属性

  • level 节点层级
  • levelStr 节点层级的字符串表示
  • expand 是否展开状态

这个遍历之后, 我们就获得了这个这个教程必备的数据, 相当于盖房子打了地基

打印看看

[ { viewNode: UiObject(id=null, sourceNodeId=-2147483650, packageName=com.sorcererxw.intentinterceptor, className=android.widget.FrameLayout, text=null, desc=null, indexInParent=-1, boundsInParent=[0,0][1080,1920], boundsInScreen=[0,0][1080,1920], checkable=false, checked=false, focusable=false, focused=false, selected=false, clickable=false, longClickable=false, enabled=true, password=false, scrollable=false),
    _level: 0,
    _levelStr: '0',
    _expand: false },
  { viewNode: UiObject(id=null, sourceNodeId=-4294967295, packageName=com.sorcererxw.intentinterceptor, className=android.widget.LinearLayout, text=null, desc=null, indexInParent=0, boundsInParent=[0,0][1080,1920], boundsInScreen=[0,0][1080,1920], checkable=false, checked=false, focusable=false, focused=false, selected=false, clickable=false, longClickable=false, enabled=true, password=false, scrollable=false),
    _level: 1,
    _levelStr: '0-0',
    _expand: false },
...
]

显示节点列表界面

let window = floaty.rawWindow(
    <frame padding="8" bg="#ccffffff">
        <androidx.recyclerview.widget.RecyclerView id="recyclerView"></androidx.recyclerview.widget.RecyclerView>
    </frame>
);

目前就只放一个recyclerview, 后期需要修改, 再改;

条目xml

<vertical>
	<horizontal>
		<img h="*">
		</img>
		<text textColor="#000000" gravity="center_vertical" h="*">
		</text>
	</horizontal>
	<View w="*" h="2px" bg="#33000000">
	</View>
</vertical>

一个img放文字左侧的图片,

一个text放className

一个view作下划线

加载节点数据

我们先加载所有节点看看效果

let rv = window.recyclerView;
let layoutManager = new LinearLayoutManager(context);
// 设置布局管理器
rv.setLayoutManager(layoutManager);
// 设置为垂直布局,这也是默认的
layoutManager.setOrientation(OrientationHelper.VERTICAL);

let recycleAdapter = createGiftBoxAdapter(viewNodesByDFS);
rv.setAdapter(recycleAdapter);
recycleAdapter.notifyDataSetChanged();

这个demo界面写出来了, 今天先到这, 有时间再写剩下的内容

环境

设备: 小米11pro
Android版本: 12
雷电模拟器:9.0.17
Android版本: 9
Autojs版本: 9.2.13

名人名言

思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程

声明

部分内容来自网络 本教程仅用于学习, 禁止用于其他用途

微信公众号 牙叔教程