easyclick dumpXml处理和json数组类型按key排序

为了方便使用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

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注