UI调试工具 SAK 布局
目录
UI调试工具 SAK 布局
SwissArmyKnife 是一款方便调试android UI的工具。可以直接在android设备屏幕上显示控件的相关信息
接入方式
compile 'com.wanjian:sak:2.0.2'
//no opt 包
compile 'com.wanjian:sak-nop:0.0.3'
//开启
SAK.init(Application application, Config config)
//关闭
SAK.unInstall();
启动app后会在屏幕右侧看到一个 蓝色靶心
,双击
即可进入功能界面。
Tips:
当开启新窗口时(包括新的Activity、弹出dialog、pop),需要手动点击一次屏幕右侧的 靶心 按钮,以此激活当前窗口
,不然当前窗口不会启用 SwissArmyKnife!
自动初始化版本
Autopilot 版基于com.wanjian:sak:xx.xx.xx
,实现了自动初始化,只需要在gradle中引入依赖即可,不需要编写额外的初始化代码
接入方式
compile 'com.wanjian:sak-autopilot:2.0.1'
//no opt 包
compile 'com.wanjian:sak-nop:0.0.3'
开启及关闭
在控制台执行 adb shell am broadcast -a com.sak
命令即可开启及关闭
支持的功能
Tips:
编辑控件、相对距离、移动控件,这几个功能相互冲突,请勿同时开启
常用的功能
- Activity、Fragment名称:可以看到当前Activity的类名,每一个Fragment的类名。
- 相对距离:依次
长按
两个控件即可显示两个控件间的水平和竖直距离
- 拾取控件:拖动圆环到要拾取的控件位置,可以获取控件id、类型、位置、背景色、宽高、边距、字体大小颜色等信息
- 取色器:会在屏幕显示绿色圆环,可以任意拖动,
屏幕下方
会显示圆环中心的颜色值(圆环的颜色也会改变) - 水平直尺、竖直直尺:会在屏幕显示水平直尺和竖直直尺,可以任意拖动进行测量,直尺上有px和dp两个值
- 边框:显示所有View的边界(类似开发者选项中的"显示布局边界"功能)
其他支持的功能
- 编辑控件:
长按
需要编辑的控件即可弹出编辑窗口,可以修改内外边距大小、宽高、背景色、字体颜色大小等 - 移动控件:
长按
控件即可拖动 - Scalpel:解剖刀,会立体显示view,可以直观的查看view的层级关系,拖动屏幕左侧的按钮可以切换角度
- 网格:显示网格
- 字体大小:显示所有TextView的大小
- 字体颜色:显示所有TextView的颜色
- 外边距:显示所有View的外边距(Margin)的大小(会填充一个背景色)
- 内边距:显示所有View的内边距(Padding)的大小(会填充一个背景色)
- 宽高:显示所有View的宽高
- 图片宽高:显示所有ImageView的宽高
- 背景色:显示所有设置background的控件的背景色的值
- 自定义信息:
- View类型:显示所有View的类型
- 布局树:显示布局树
- 性能:可以看到当前窗口view的绘制耗时、事件分发耗时、measure耗时、layout耗时、handler耗时等信息
- 开启后会自动禁用硬件加速,实际绘制时间可能要少一些
- ListView会在事件分发时调用getView,所以ListView事件分发时间稍微长一些
- RecyclerView会在view绘制时bindView,所以RecyclerView绘制时间会稍长一些
可配置项
可配置项
- 层级区间:Fragment名称、外边距、内边距、宽高、字体大小、字体颜色、背景色等功能下,可以通过设置
层级区间
过滤掉部分view,避免数值相互覆盖 - 单位:距离默认单位是dp,可以切换为dp、sp、px单位
- 裁剪绘制范围:若内外边距、宽高、字体颜色等信息不显示,可以关闭 裁剪绘制。开启该功能可以避免
可以滚动的控件滚动后导致的信息覆盖
问题。
原理
实现过程:
- 监听window的创建,从而拿到每一个window的根view。
- 拿到根view(必须是FrameLayout或RelativeLayout)后给根view添加
RootContainerView
,RootContainerView
内部包含了蓝色的靶心view。每个window都有一个专用的RootContainerView
。 - 创建各window共用的
DashBoardView
,DashBoardView
是其他各功能view的容器,比如开启取色功能后会把TakeColorView
加到DashBoardView
中。 - 双击当前窗口的靶心按钮会在当前窗口激活 SwissArmyKnife,其实是把共用的
DashBoardView
添加到了当前窗口的RootContainerView
中。 - 每一个功能都是
AbsLayer
的子类,AbsLayer
继承自FrameLayout
。当当前窗口的任何一个view需要绘制时都会调用AbsLayer
的onUiUpdate
方法,可以在该方法里绘制相关信息,比如边框,字体颜色等。
自定义功能
可以通过 Config 对 SAK 进行配置或自定义功能。
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
Config config = new Config.Build(this)
.viewFilter(getViewFilter())
.addLayerView(getLayerView())
.addSizeConverter(getSizeConverter())
.build();
SAK.init(this, config);
}
private ISizeConverter getSizeConverter() {
return new ISizeConverter() {
// 可以添加自定义的SizeConverter,默认提供了Origin*、Px2Dp*,Px2Sp*
@Override
public String desc() {
return "my converter";
}
@Override
public Size convert(Context context, float length) {
return Size.obtain().setLength(length / 2).setUnit("myU");
}
@Override
public int recovery(Context context, float length) {
return 0;
}
};
}
private AbsLayer getLayerView() {
// 可以添加自定义的view,自定义的view要继承自AbsLayer或其子类,AbsLayer是FrameLayout的子类
// 当激活SwissArmyKnife时会调用 onAttached(View rootView)方法,rootView是当前window的根view,比如Activity的根view DecorView。
//当停用是会调用`onDetached`
return new AbsLayer(this) {
@Override
public String description() {
return null;
}
@Override
public Drawable icon() {
return null;
}
};
}
private ViewFilter getViewFilter() {
return new ViewFilter() {
@Override
public boolean apply(View view) {
// 这里可以决定要显示哪种view,比如只显示ImageView子类和LinearLayout子类
// 若想要显示所有可见的view,直接返回 view.getVisibility()==View.VISIBLE 即可
return view instanceof ImageView || view instanceof LinearLayout;
}
};
}
}
2019-6-30
本文来自博客园,作者:白乾涛,转载请注明原文链接:https://www.cnblogs.com/baiqiantao/p/11108512.html