autojs自己写布局分析(二)

1,221 阅读2分钟

牙叔教程 简单易懂

\

在上一个教程: autojs自己写布局分析中, 我们绘制了绿框

www.yuque.com/yashujs/bfu…

今天我们要实现的是点击绿框, 弹出点击的节点信息, 就像这样子

思路

手指点击屏幕, 有了一个触摸坐标, 拿触摸坐标和节点的矩形区域作对比, 如果包含该点,

那么就弹出对应节点的信息

设置画板的点击事件

我们在抬起事件中, 获取触摸坐标x,y 传给函数 showDialog

//记录按键被按下时的触摸坐标
var x = 0,
    y = 0;
window.canvas.setOnTouchListener(function (view, event) {
    switch (event.getAction()) {
        case event.ACTION_DOWN:
            log("ACTION_DOWN");
            break;
        case event.ACTION_MOVE:
            log("ACTION_MOVE");
            break;
        case event.ACTION_UP:
            log("ACTION_UP");
            x = event.getRawX();
            y = event.getRawY();
            showDialog(x, y);
            break;
    }
    return true;
});

\

判断点是否在矩形区域内

显示对话框之前, 我们要先遍历所有节点, 看点位是否在某个绿框之内

function isPointInRect(point, rect) {
    let x = point.x;
    let y = point.y;
    let x1 = rect.left;
    let y1 = rect.top;
    let x2 = rect.right;
    let y2 = rect.bottom;
    if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
        return true;
    }
    return false;
}

\

遍历判断点是否在某个绿框内部

遍历所有的绿框节点

function showDialog(childViewNodes, x, y) {
    var len = childViewNodes.length;
    // 倒序遍历
    for (var i = len - 1; i >= 0; 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;
        if (x > left && x < right && y > top && y < bottom) {
            log("点击了第" + i + "个元素");
            log(childViewNodes[i]);
            break;
        }
    }
}

点击一下, 看看效果

点击了第4个元素 

UiObject(id=, sourceNodeId=3826815860980, packageName=org.autojs.autojspro, className=android.view.View, text=null, desc=UI界面.js
28.46 KB
修改于 2022-09-29 17:22:54, indexInParent=0, boundsInParent=[0,0][1440,233], boundsInScreen=[0,669][1440,902], checkable=false, checked=false, focusable=true, focused=false, selected=false, clickable=true, longClickable=true, enabled=true, password=false, scrollable=false) 

\

获取要显示的节点信息

autojs的节点有以下条目, 我们封装成模块, 方便调用

// 属性名字
let propertyNames = [
    "accessibilityFocused",
    "bounds",
    "checked",
    "className",
    "clickable",
    "column",
    "columnCount",
    "columnSpan",
    "columnSpan",
    "depth",
    "desc",
    "dismissable",
    "drawingOrder",
    "editable",
    "enabled",
    "focusable",
    "fullId",
    "id",
    "idHex",
    "indexInParent",
    "longClickable",
    "packageName",
    "row",
    "rowCount",
    "rowSpan",
    "scrollable",
    "selected",
    "text",
    "visibleToUser",
];

module.exports = propertyNames;

节点中的这些属性对应的值, 有的是方法, 有的是布尔值,

因此我们还要判断一下值的类型, 如果是函数, 那么就执行函数, 否则直接赋值即可

判断变量类型

function getVariableType(variable) {
    return Object.prototype.toString.call(variable);
}

判断变量是不是函数

function isFunctionType(variable) {
    let variableType = getVariableType(variable);
    if (variableType === "[object Function]") {
        return true;
    } else {
        return false;
    }
}

获取节点信息

function getViewNodeInfoDialog(viewNode) {
    var len = propertyNames.length;
    let arr=[]
    for (var i = 0; i < len; i++) {
        var propertyName = propertyNames[i];
        let value = viewNode[propertyName];
        if (isFunctionType(value)) {
            value = value();
        }
        if (getVariableType(value) === "[object Null]" || getVariableType(value) === "[object Undefined]") {
            value = "";
        }
        arr.push({
            name: propertyName,
            value: value
        })
    }
    return arr;
}

打印看看

[ { name: 'accessibilityFocused', value: false },
  { name: 'bounds', value: Rect(0, 669 - 1440, 902) },
  { name: 'checked', value: false },
  { name: 'className', value: 'android.view.View' },
  { name: 'clickable', value: true },
  { name: 'column', value: -1 },
  { name: 'columnCount', value: 0 },
  { name: 'columnSpan', value: -1 },
  { name: 'columnSpan', value: -1 },
  { name: 'depth', value: 13 },
  { name: 'desc',
    value: 'UI界面.js\n28.46 KB\n修改于 2022-09-29 17:22:54' },
  { name: 'dismissable', value: false },
  { name: 'drawingOrder', value: 0 },
  { name: 'editable', value: false },
  { name: 'enabled', value: true },
  { name: 'focusable', value: true },
  { name: 'fullId', value: '' },
  { name: 'id', value: '' },
  { name: 'idHex', value: '' },
  { name: 'indexInParent', value: 0 },
  { name: 'longClickable', value: true },
  { name: 'packageName', value: 'org.autojs.autojspro' },
  { name: 'row', value: -1 },
  { name: 'rowCount', value: 0 },
  { name: 'rowSpan', value: -1 },
  { name: 'scrollable', value: false },
  { name: 'selected', value: false },
  { name: 'text', value: '' },
  { name: 'visibleToUser', value: true } ] 

信息显示到对话框

对话框的基本样式

importClass(android.graphics.drawable.GradientDrawable);

  

let view = ui.inflate(<text>牙叔教程</text>, null, false);

let dialog = dialogs.build({

 customView: view,

});

let dialogWindow = dialog.getWindow();

setBackgroundRoundRounded(dialogWindow);

dialog.show();

  

function setBackgroundRoundRounded(view) {

 let gradientDrawable = new GradientDrawable();

 gradientDrawable.setShape(GradientDrawable.RECTANGLE);

 gradientDrawable.setColor(colors.parseColor("#c8e6c9"));

 gradientDrawable.setCornerRadius(60);

 view.setBackgroundDrawable(gradientDrawable);

}

\

autojs的对话框分析

有以下几个特点:

  • 圆角
  • 可以滚动
  • 有分割线
  • 有确定按钮

布局

<vertical padding="8">
    <list id="list" layout_weight="1">
      ...
    </list>
    <text>
        确定
    </text>
</vertical>,

listView我们需要修改一下字体大小和颜色

function createAdapter(adapter, textSize, textColor) {
    let result = new JavaAdapter(RecyclerView.Adapter, {
        onCreateViewHolder: function (parent, viewType) {
            return adapter.onCreateViewHolder(parent, viewType);
        },
        onBindViewHolder: function (vh, i) {
            adapter.onBindViewHolder(vh, i);
            vh.itemView.name.setTextSize(textSize);
            vh.itemView.name.setTextColor(colors.parseColor(textColor));
            vh.itemView.value.setTextSize(textSize);
            vh.itemView.value.setTextColor(colors.parseColor(textColor));
        },
        getItemCount: function () {
            return adapter.getItemCount();
        },
    });
    return result;
}
let adapter = createAdapter(recyclerView.getAdapter(), textSize, textColor);
recyclerView.setAdapter(adapter);

界面效果如下

到这里对话框就做完了, 有时间的话继续写布局分析的其他功能

环境

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

名人名言

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

声明

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

微信公众号 牙叔教程