我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第9篇文章,点击查看活动详情
牙叔教程 简单易懂
要达到的效果
autojs自带的布局分析是这样的
\
绿框里面是控件的节点信息, 我们要展示绿框, 首先要提取当前界面的节点信息;
根节点
let windowRoot = auto.rootInActiveWindow;
log(windowRoot);
UiObject(id=null, sourceNodeId=-2147483650, packageName=org.autojs.autojspro, 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)
\
屏幕上绘制多少个绿框
如果节点有几十几个百个, 问题不大, 如果有几千个呢?
节点太多, 会影响绘制绿框的速度;
因此, 我们要限制绿框的数量.
假设节点有上千个, 我们绘制那些绿框呢?
\
图中一共有6个节点, 如果我们只绘制3个节点,
那么我们绘制谁呢?
用户需要使用什么, 我们就绘制什么.
一般我们选择节点都不会是顶端的节点, 而是偏向底层的节点,
因此, 我们应该绘制DEF这三个节点.
如何获得DEF三个节点信息
必然要从根节点开始遍历
怎么遍历节点
遍历节点有2种方式: 深度(Depth First)和广度(Breadth First),
我们要获取的节点是DEF, 这三个节点是同一层的节点, 应当用 广度( Breadth First ) ;
BF遍历代码
- 获取当前界面根节点
let windowRoot = auto.rootInActiveWindow;
- 变量 viewNodes 存储节点
let viewNodes = [];
viewNodes.push(windowRoot);
- 存储根节点的直接子节点
let viewNodes = [];
viewNodes.push(windowRoot);
var childCount = windowRoot.childCount();
for (var i = 0; i < childCount; i++) {
let childViewNode = windowRoot.child(i);
viewNodes.push(childViewNode);
}
- 第二层我们访问完了, 接着该访问第三层了, 按照第二层子节点的顺序, 一次访问第三层;
var childCount = secondLevelViewNodeA.childCount();
for (var i = 0; i < childCount; i++) {
let childViewNode = secondLevelViewNodeA.child(i);
viewNodes.push(childViewNode);
}
以此类推
- 第三层访问完了, 接着访问第四层
var childCount = thirdLevelViewNodeA.childCount();
for (var i = 0; i < childCount; i++) {
let childViewNode = thirdLevelViewNodeA.child(i);
viewNodes.push(childViewNode);
}
\
- 节点的层数是不确定的, 我们也不清楚当前还有哪些节点需要遍历, 因此, 我们要一个队列, 来存储需要遍历的节点, 显而易见的, 我们要写一个 广度( Breadth First ) 递归
function findViewNodes(viewNode) {
let viewNodes = [];
let breadthViewNodes = [];
// 节点加入队列
breadthViewNodes.push(viewNode);
// 遍历队列中的节点
while (breadthViewNodes.length > 0) {
let headViewNode = breadthViewNodes.shift();
// 子节点入队列
let childCount = headViewNode.childCount();
for (let i = 0; i < childCount; i++) {
let childViewNode = headViewNode.child(i);
breadthViewNodes.push(childViewNode);
}
// 父节点入库
viewNodes.push(headViewNode);
}
return viewNodes;
}
这一段代码也许有的人不太好理解, 大家可以想象一下, 机关枪;
子弹发射之后, 一颗子弹 有概率 变成两颗, 三颗, 然后重新回到弹夹中,
弹夹空了以后, 我们就获得了所有不会再分裂的子弹.
并且, 这些子弹都是按分裂的次数, 就和游戏里宝宝变异的不同级别一样,
每层都是同等级变异的宝宝, 这体现了数据的顺序性.
\
限制绘制的绿框数量
我们可以把限制的数量, 放到一个配置中, 方便后期修改;
这里我们指定限制绘制10个绿框;
上面解析了所有的节点, 存到了一个数组中,
用户常用的是节点面积区域最小的节点, 因此我们从后往前截取10个节点;
let viewNodes = findViewNodes(windowRoot);
let childViewNodes = viewNodes.slice(-10)
绘制绿框
我们要的节点数据有了, 主要是节点的bounds数据;
下面开始绘制, 绘制的话, 先创建一个全屏悬浮窗, 然后多次绘制矩形
let paint = new Paint();
paint.setColor(colors.parseColor("#00ff00"));
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
window.canvas.on("draw", function (canvas) {
var len = childViewNodes.length;
for (var i = 0; i < len; i++) {
let childViewNode = childViewNodes[i];
let bounds = childViewNode.bounds();
let left = bounds.left;
let top = bounds.top;
let right = bounds.right;
let bottom = bounds.bottom;
canvas.drawRect(left, top, right, bottom, paint);
}
});
\
到这里本篇教程的目的: 绘制绿框, 就达到了;
之后有时间了, 会继续模仿autojs的布局分析
环境
设备: 小米11pro
Android版本: 12
雷电模拟器:9.0.17
Android版本: 9
Autojs版本: 9.2.13
名人名言
思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问 --- 牙叔教程
声明
部分内容来自网络 本教程仅用于学习, 禁止用于其他用途