为了方便使用html来分析安卓的布局,花时间做了一下xml节点转html,做个分析过程笔记,讲下大致原理。
在处理dumpXml档时,类似xml文档 hierarchy rotation="0"
<hierarchy rotation="0">
<node drawingorder="0" index="0" layer="2" depth="0" text="" clz="android.widget.FrameLayout" pkg="com.android.systemui" desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" longclickable="false" password="false" selected="false" nid="android.view.accessibility.AccessibilityNodeInfo@bf88" id="" visible="true" multiline="false" dismissable="false" editable="false" bounds="[0,0][720,55]" left="0" top="0" right="720" bottom="55" parentid="android.view.accessibility.AccessibilityNodeInfo@bf88" childcount="5">
……
</node>
</hierarchy>
我先是将它转化为json数据,
然后转换成html代码呈现网页
但是,层次问题引起了些问题,纠结了许久
解析成json分为object子节点对象和ArrayObject子节点同级列表两种。
层次嘛,遍历时用levers来累加层级,用div嵌套每个子节点。
使用position:absolute;绝对定位,因为div嵌套,左上角left,top值简单处理一下
curLeft=Number.parseInt(curNode.left);
curTop=Number.parseInt(curNode.top);
let left=curLeft-parentLeft-1; //相对父级节点
let top=curTop-parentTop-1; //相对父级节点
let right=Number.parseInt(curNode.right);
let bottom=Number.parseInt(curNode.bottom);
let width=right-Number.parseInt(curNode.left); //节点宽
let height=bottom-Number.parseInt(curNode.top);
z_index=levels+Number.parseInt(curNode.depth); //css层级
//是否数组
function isJsArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
//是否对象
function isJsObject(obj) {
return Object.prototype.toString.call(obj) == '[object Object]';
}
//……此处省略繁杂代码
let childNode=curNode.node;
if(typeof childNode != "undefined"){
if(isJsObject(childNode)){
levels+=1000;
htmls+=jsonToHtml(childNode,curTop,curLeft,levels);
}
if(isJsArray(childNode)){
levels+=1000;
//遍历多个同级子元素,使用drawingorder来排序,解决层次错乱问题
childNode.sort(function(a,b){
return a.drawingorder - b.drawingorder;
});
$.each(childNode, function (index, item) {
levels+=100;
htmls+=jsonToHtml(item,curTop,curLeft,levels);
});
}
}
并且把div点击穿透处理一下,一共两点,css和js事件
css判断部分,通过clickable来判断div是否应用点击穿透。
//pointer-events:none 可穿透,auto或者fill不穿透
let clickevent='none';
let clickable=curNode.clickable; //可点击层
let focusable=curNode.focusable;
let cursorStyle="default";
//clickable focusable 为真实可点击 单clickable为滑动层
if(clickable==='true'){
clickevent='fill'; //阻止穿透
cursorStyle="pointer";
}
js事件判断部分
//点击事件穿透父级判断
$('.div').on('click',function(e){
let bounds=$(this).attr("bounds");
let clickable=$(this).attr("clickable");
let focusable=$(this).attr("focusable");
if(clickable && focusable) e.stopPropagation(); //阻止父元素穿透点击
if(typeof bounds != "undefined"){
console.log('测试点击范围:'+bounds);
}
});
//其它操作事件模拟类似。比如右击,滑动等等其它。
div样式处理一下,用内边框吧。
box-sizing: border-box; /*内边框*/
overflow:hidden;
padding:0;margin:0;
关于字体大小,用屏宽除于42,你可以自行调节。
将大部分节点背景设为透明,把这几个css背景设为白色#FFF,方便多层视图隔离
android.view.View
android.view.ViewGroup
android.widget.ListView
这样用html分析dumpXml出来的node布局就处理完成了。
看看效果,抽时间再把完整代码放在github
