Skip to content

Commit 3a2a6df

Browse files
author
吴广靓
committed
初稿发布
Signed-off-by: 吴广靓 <v-wuguangliang@xiaomi.com>
1 parent dece870 commit 3a2a6df

9 files changed

Lines changed: 141 additions & 28 deletions

File tree

README.md

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,129 @@
11
# DimensAuto
2-
Android自动转换dimens的gradle脚本,当前版本:v1.1.2
2+
[![](https://img.shields.io/badge/version-1.2.0-orange?branch=master)](https://img.shields.io/badge/version-1.2.0-orange)
3+
[![](https://img.shields.io/github/issues/developer-wgl/DimensAuto?branch=master)](https://img.shields.io/github/issues/developer-wgl/DimensAuto)
4+
[![](https://img.shields.io/github/stars/developer-wgl/DimensAuto?branch=master)](https://img.shields.io/github/stars/developer-wgl/DimensAuto)
5+
[![](https://img.shields.io/github/forks/developer-wgl/DimensAuto?branch=master)](https://img.shields.io/github/forks/developer-wgl/DimensAuto)
6+
[![](https://img.shields.io/github/license/developer-wgl/DimensAuto?branch=master)](https://img.shields.io/github/license/developer-wgl/DimensAuto)
37

8+
一款开发无感知的 `dimens` 自动化转换工具、 `gradle` 插件脚本
49

10+
## 背景
11+
去年刚加入小爱,对于小米这种适配`values-nxhdpi`情况很不适应,有几点写业务的时候很不爽:
12+
- 每次人工映射效率低;
13+
- 更改一处值,另一处忘记更改时,UI/测试对于部分机型都不会看出问题,容易出错;
14+
- 新同事可能并不了解此适配,项目中有很多并未适配的 `dimens` 键值,另外沟通还需要额外工作;
515

6-
### 优势:
16+
<br>
17+
其实网上对于这种自动化脚本已经很多了,而且小爱这边也是有有同学写过这种类似脚本的,那我为什么还要决定在搞一个呢?
718

8-
1. 可自定义配置转换规则;
9-
2. 编译时自动运行、一次到位,让开发无感知自动化;
10-
3. 同配置,多module转换;
11-
4. 跨平台,支持版本控制;
12-
5. 用起来爽到爆。
19+
- 冲浪了很久。发现都需要单独运行,然后拷贝到项目中、每次改值重新生成,对于有强迫症、比较关心开发效率的我总是感觉很不爽(就是懒、嫌麻烦~
20+
<br>
1321

22+
所以针对以上几点,在工作之余花了几个小时写了 Android Studio 插件 [DimensPlugin](https://github.com/developer-wgl/DimensPlugin),可在 IDE 中通过 `‘划词’` 这种形式,划取想要的 `dimens` 再使用 `快捷键` 就可以将选中的键值进行自动转换。
1423

24+
但是在组内推广过程中,其实还是有额外成本的和常见的插件并未有很大差别。经过和同事讨论,得到了一些建议,于是就有了此完全自动化的脚本插件,也经过小爱这边线上项目实践未出现过问题,收到同事一致好评~
1525

16-
只有一个[脚本文件](./dimens_auto.gradle)拷贝到项目中,并添加到 build.gradle 中允许即可。
26+
说了这么多废话,这东西到底哪点方便呢?
27+
28+
## 与其他相比,优势在哪?
29+
30+
1. Gradle 插件脚本,在编译时会自动转换;
31+
- 编译和 `dimens` 数量有关,大数量时,也能在 10ms 以内搞定。编译时会有耗时输出;
32+
- 编译时会自动生成对应文件夹及文件,对项目旧版 `dimens` 兼容;
33+
- 编译时会有提示、警告、错误输出;
34+
- 可针对 `module` 单独配置,也可以全局配置;
35+
- 开发只需填写一份 `dimens` 无感知其他`dpi`生成;
36+
- 配置简单,只需要一行代码;
37+
2. 支持自定义配置扩展,可全局配置;
38+
3. 脚本大小 8K,不会被编入`APP`包内;
39+
4. 支持跨平台开发,已适配 linux、mac、window 平台;
40+
5. 支持 `git` 等代码管理工具动态管理;
41+
42+
43+
## 如何配置
44+
45+
1. 下载 [dimens_auto.gradle](./dimens_auto.gradle)
46+
2. 在需要使用此插件的 `module` 中的 `build.gradle` 文件头部按照以下操作加入代码:
47+
48+
``` gradle
49+
// module内使用此方式使用
50+
// 若将 `dimens_auto.gradle` 以拷贝至项目根目录时(其他位置注意路径引入即可),引入方式如下:
51+
apply from: "../dimens_auto.gradle"
52+
```
53+
3. 打开项目内的 `dimens_auto.gradle` 自定义配置参数,可配置参数如下:
54+
打开tools.gradle 针对自己项目更改配置参数,可配置参数如下:
55+
56+
```gradle
57+
/* 参数配置 */
58+
def config = [
59+
"dimens_path" : "", // 要转换的 `dimens_auto.xml` 相对、`module`的路径.
60+
"convert_rules": [], // 转换规则,可自定义扩展。 如 :["hdpi": 3/1.5,"xhdpi": 3/2,"sw600dp-xhdpi": 3/2,"nxhdpi": 3/2.75,"xxxhdpi": 3/4]
61+
"convert_unit" : [], // 要转换的单位。 如 ["dp", "dip", "sp"]
62+
"decimal" : 2, // 转换后小数点保留位数
63+
"init_hint" : "", // 文件初次创建时的提示语句
64+
"help_url" : "", // 帮助文档
65+
"debug" : false
66+
]
67+
```
68+
69+
4. 点击 IDE “运行“ 按钮运行项目,build过程中可以看到 `dimens auto:` 日志输出。如果没有异常输出并且 `src/res` 中已经存在了你配置的 `dimens_auto` 文件则说明配置成功。
70+
71+
![Android Studio run](./imgs/result.png)
72+
73+
74+
## 如何使用
75+
76+
使用常见设计稿中的 `xxhdpi@3x` 中的值(如果设计稿中没有@3x选项,可按照此方式处理:`xxhdpi@3x` = px值/3)放到默认 `values/dimens_auto.xml` 里面按照正常开发去使用就可以了,没了..
77+
78+
<p align="center">
79+
<img src="./imgs/ui_1.png" height="400px;" />
80+
</p>
81+
82+
83+
## 遇到问题?
84+
85+
1. 何时被执行(转换)
86+
* 自动执行:Android Studio 编译时会被默认执行
87+
88+
<img src="./imgs/ide_run.jpg"/>
89+
90+
91+
* 手动执行:打开 `dimens_auto.gradle` 点击task 左侧按钮运行
92+
![Android Studio run](./imgs/run_1.png)
93+
94+
* 手动执行:打开Android Studio 打开菜单 View → Tool Windows → Gradle → Project Name → Tasks → other → dimens_auto 双击执行
95+
96+
![Android Studio run](./imgs/run_2.png)
97+
98+
99+
2. 不想被转换怎么办
100+
- dimens_auto.gradle中会有一些参数配置,并不是所有放在 `dimens_auto.xml` 的值都会被转换。默认配置为只处理`【dp、dip、sp】`,未被转换时会抛出警告。如果你不想被转换的值就是dp、dip、sp,那请看下一条.
101+
102+
- 当前转换逻辑为处理当前module中的默认名为 `dimens_auto.xml` 的文件进行转换,所以把自己不想自动转换的值放到其他dimen文件中即可,如默认的dimens.xml。
103+
104+
105+
4. 原理是什么
106+
把默认的dimens值设为1,在代码编译时会根据配置比例进行转换。
107+
至于匹配规则通过正则编写,至于生成使用的是gradle库进行的生成。 
108+
109+
5. 转换需要多长时间
110+
自动转换了5个对应的dimens文件,耗时 118 ms .   只转换 default → nxhdpi 耗时 25 ms.,根据电脑性能有关。
111+
 
112+
6. 只想局部转换怎么办
113+
我写的一个Idea/Android Studio 插件,可以划词选中后按快捷键自动转换:[DimensPlugin](https://github.com/developer-wgl/DimensPlugin)
114+
115+
116+
7. 目前支持哪种格式的dimens转换
117+
目前已做适配的有以下三种。其他格式的可以自己编译看下转换后的结果,可能也会支持。
118+
119+
![Android Studio run](./imgs/support_dimens.png)
120+
     
121+
8. 关于跨平台问题(linux/MAC/windows)
122+
- windows 运行后不能运行,有乱码产生,已修复;
123+
- windows 平台运行后有系统换行符(LF/CRLF)change问题,已修复;
124+
125+
126+
## 沟通交流
127+
写一个开源工具和一套完整的文档实属不易。如果觉得还可以,跪求留下你的 `Star` 鼓励下~
128+
129+
欢迎 [issues](https://github.com/developer-wgl/DimensAuto/issues) ,留下你遇到的问题和宝贵的建议,我很愿意与你一起成长技术~

dimens_auto.gradle

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
group = "tools"
2-
version = "1.1.2"
2+
version = "1.2.0"
33

44
task dimens_auto(type: ConvertDimensTask) {
55

66
/* 参数配置 */
77
config = [
88
"dimens_path" : "src${File.separator}main${File.separator}res${File.separator}values${File.separator}dimens_auto.xml",
9-
"convert_rules" : ["xhdpi": 1, "sw600dp-xhdpi": 3 / 2],
10-
"to_convert_unit": ["dp", "dip", "sp"],
9+
"convert_rules" : ["xxhdpi": 1, "sw600dp-xhdpi": 3 / 2],
10+
"convert_unit": ["dp", "dip", "sp"],
1111
"decimal" : 2,
12-
"help_url" : "https://wiki.n.miui.com/x/54XaDw",
12+
"init_hint" : "可在此处写入默认dimens,编译时即可自动转换为相应配置的dimens.",
13+
"help_url" : "https://github.com/developer-wgl/DimensAuto",
1314
"debug" : false
1415
]
1516

@@ -27,17 +28,18 @@ class ConvertDimensTask extends DefaultTask {
2728

2829
@Optional
2930
def config = [
30-
"dimens_path" : "", // 要转换的文件路径
31-
"convert_rules" : [], // 转换规则,可自定义扩展。 如 :["sw600dp-xhdpi": 3/2,"nxhdpi": 3/2.75]
32-
"to_convert_unit": [], // 处理转换的单位。 如 ["dp", "dip", "sp"]
33-
"help_url" : "", // 帮助文档
34-
"decimal" : 2, // 转换后小数点保留个数
35-
"debug" : false
31+
"dimens_path" : "", // 要转换的 `dimens_auto.xml` 相对、`module`的路径.
32+
"convert_rules": [], // 转换规则,可自定义扩展。 如 :["hdpi": 3/1.5,"xhdpi": 3/2,"sw600dp-xhdpi": 3/2,"nxhdpi": 3/2.75,"xxxhdpi": 3/4]
33+
"convert_unit" : [], // 要转换的单位。 如 ["dp", "dip", "sp"]
34+
"decimal" : 2, // 转换后小数点保留位数
35+
"init_hint" : "", // 文件初次创建时的提示语句
36+
"help_url" : "", // 帮助文档
37+
"debug" : false // 输出更多调试日志,便于排查问题
3638
]
3739

3840
def analyze() {
39-
if (!config.dimens_path || !config.convert_rules || !config.to_convert_unit) {
40-
getLogger().log(LogLevel.ERROR, "${TAG}规则没有被使用")
41+
if (!config.dimens_path || !config.convert_rules || !config.convert_unit) {
42+
getLogger().log(LogLevel.ERROR, "${TAG}没有转换配置可用,请检查转换配置")
4143
return
4244
}
4345

@@ -47,17 +49,15 @@ class ConvertDimensTask extends DefaultTask {
4749
if (config.debug) {
4850
println TAG + defaultXmlFile.isDirectory()
4951
}
50-
if (!newDimensFile.isDirectory()) {
51-
newDimensFile.getParentFile().mkdirs()
52+
if (!defaultXmlFile.isDirectory()) {
53+
defaultXmlFile.getParentFile().mkdirs()
5254
}
5355
if (!defaultXmlFile.createNewFile()) {
5456
throw new Exception("ERROR: dimens文件创建失败,未进行dimens转换: " +
5557
defaultXmlFile.getAbsolutePath() + " ${getIdentityPath()}:dimens_auto.")
5658
} else {
5759
def init = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
58-
"<resources>\n" +
59-
" <!-- 可在此处写入默认dimens,编译时即可自动转换为相应配置的dimens. -->\n" +
60-
"</resources>"
60+
"<resources>\n\t<!-- ${config.init_hint} -->\n</resources>"
6161
defaultXmlFile.text = init
6262
}
6363
}
@@ -68,7 +68,7 @@ class ConvertDimensTask extends DefaultTask {
6868

6969
// edit regex to get dimens value and unit
7070
def unit = ''
71-
config.to_convert_unit.each {
71+
config.convert_unit.each {
7272
unit += it + "|"
7373
}
7474
def unitRegex = ~"([-0-9.]{1,10})(${unit[0..-2]})"
@@ -78,7 +78,7 @@ class ConvertDimensTask extends DefaultTask {
7878

7979
// real convert by rules
8080
for (def rule in config.convert_rules) {
81-
println "${TAG}convert unit:${config.to_convert_unit}, rule:default(1) -> ${rule.key}(${rule.value})"
81+
println "${TAG}convert unit:${config.convert_unit}, rule:default(1) -> ${rule.key}(${rule.value})"
8282

8383
File newDimensFile = copyDimensFile(defaultXmlFile, rule)
8484
if (config.debug) {
@@ -170,7 +170,7 @@ class ConvertDimensTask extends DefaultTask {
170170
def append = "${'\n'}\t此文件由默认 ${newDimensFile.getName()} 文件自动转换处理,除合并代码外勿编辑!"
171171
if (config.debug) {
172172
append += '\n'
173-
append += "${'\n'}\t转换处理单位有:${config.to_convert_unit}"
173+
append += "${'\n'}\t转换处理单位有:${config.convert_unit}"
174174
append += "${'\n'}\t此处转换逻辑为:default(1) -> ${rule.key}(${rule.value})"
175175
append += "${'\n'}\t共找到节点数量:${xml.children().size()} , 共转换节点数量:${convert_count}"
176176
}

imgs/gradle_run.png

25.7 KB
Loading

imgs/ide_run.jpg

5.12 KB
Loading

imgs/result.png

50.3 KB
Loading

imgs/run_1.png

26.3 KB
Loading

imgs/run_2.png

67.4 KB
Loading

imgs/support_dimens.png

12.8 KB
Loading

imgs/ui_1.png

32.1 KB
Loading

0 commit comments

Comments
 (0)