2333,看这标题就知道不是什么正经技术文章,花了点时间,写了个「无用良品」,之后请叫我「Android界爱迪生——樊少皇」,蟹蟹~android
最近公司APP版本迭代,一我的写界面,写到我真的想吐:算法
有些路人可能会说:不喜欢写,你不会拖拉控件吗,憨憨。app
可能各位都是:i9 9900K,850 PRO,64G DDR4,拖拽控件丝滑流畅,不知人间疾苦…
若是您像小弟同样用着公司配的:i3家用台式机,你也会秒变「祖安人」布局
拖拽卡顿不灵活不说,拖拽完还得进代码调来调去,有时效率还不如手敲。
Google好久之前出的ConstraintLayout约束布局是挺好用的,就是要写多一堆属性,好比每一个控件必不可少的:优化
虽然说AS自动补全,可是写起来,效率并非很高。做为一个「具备4点多堆砌布局经验的Android开发仔」一个重要的标准就是:看到一个设计图,立马在心中解析出「页面布局的层次结构」好比这样的我的中心的页面:spa
直接解析:翻译
约束布局 相对布局 回退- Button 标题-TextView 卡片视图 约束布局 头像-ImageView 登录提示-TextView 更多箭头-ImageView 卡片视图 约束布局 订单图标-ImageView 订单文本-TextView 订单更多-ImageView 兑换图标-ImageView 兑换文本-TextView 兑换更多-ImageView...略复制代码
解析却是挺简单,不顾敲起来,大部分是机器式重复,。前不久在逼乎上看到这段话:设计
以为还挺有道理,着实须要一种智识和能力去改进,从这样的「时间泥潭」中跳出。3d
脑海中萌生了「模板代码」思路:code
和AS自带新建布局模板的方式有点不同,精确到控件级别,用 关键字匹配 控件对应的模板代码。
当我输入tv的时候,导入对应的一大串代码,输入tvc的时候导入另外一串代码。
不过这个思路在我写完一个TextView后就放弃了,TM的那么多控件,要写多少套,并且不少属性是多余的…
这种思路妥妥滴不行,因而又萌生了另外一种思路:
「定义一套本身的语法规则,写少许,用脚本翻译成AS里的XML文件」
啧啧啧,这样也意味着能够
「能够脱离Android Studio写布局文件,并且比一个个字母手敲xml高效!」
想一想,你能够「在地铁上用便签写布局,而后到公司用脚本直接翻译成XML布局」太酷了吧!
定义这套语法规则以前,咱们先要了解一下xml布局的规律:
# XML由一个个标签(结点)构成,分为:单标签 和 双标签(可嵌套),如:<TextView .../> 和 <LinearLayout ..></LinearLayout> # 而后标签的组成<控件名 属性:值 属性:值 .../>复制代码
综上,不可贵出两个规律:
① 标签其实有三种: 开标签, 关标签, 闭合标签,要进行区分
② 标签 = <控件名 若干 属性:值>
另外,Android是建议,每一个控件都设置一个id属性的,不难定义一个类来表明一个标签:
class Node: def __init__(self, widget=None, id=None, kv=None): self.widget = widget self.id = id self.kv = kv复制代码
上面也说了,标签由三种,这里引入三个符号来进行标记(+-*),好比:
+ 线性布局 * 文本视图- 线性布局复制代码
新建配置文件config.ini用于保存「自定义简称 与 控件的映射关系」
注意:这里的简称能够定义成你本身喜欢的,中文也行!
接着写个读取配置文件的脚本config_getter.py,读取下:
再接着新建一个输入源test.txt文件,内容以下:
最后写脚本读取txt文件,按行读取,过滤空格和换行,根据字符串第一个字符进行过滤:
运行后能够看到输出的xml文件:
堆一块儿,看不出什么,格式化看看效果:
啧啧啧,有内味了。
一个控件能够有多个属性,多个属性怎么进行分割呢?笔者用的是「>」
而后属性和值又怎么分割呢?原本是想用 :或| 的,后面发现都用到了,最后决定用「-」来分割。
一个简单的示例以下:
* bt > bt_back > w-56 > h-56 > t-返回 复制代码
上述的代码表明:
定义一个按钮,id为bt_back,宽56dp,高56dp,文本为返回
另外,有些经常使用的属性-值,能够简化下,好比:
android:layout_width="wrap_content"# 能够写成w-wrap_content# 简化w-w# 再简化ww复制代码
用 ww 就能够代替:android:layout_width="wrap_content"
程序处理的时候须要对:w-w 和 ww进行区分,区分方法也很简单:
len(split("-")) == 1,说明是后者,不然是前者
啧啧啧,能够,继续~
值的情形稍微复杂一点,常见的有下面这些:
android:gravity="center|start"android:layout_width="match_parent"android:background="@drawable/ic_back_white"android:layout_marginStart="60dp"app:layout_constraintDimensionRatio="16:9"复制代码
其实划分下,笔者须要只需区分三种类型
- ① 直接填充 -> 属性="xxx"
- ② 数字dp -> 属性="xdp"
- ③ @资源引用 -> 属性="@x/y"
因此处理的流程:
Step 1:判断是否为数字,是的话加上dp,不然跳Step 2
Step 2:利用正则判断是否为@类型,是的话提取下类型与值,不然跳Step3
Step 3: 判断是否包含此属性,是填充模板,不然直接填充
也很简单,接下来就是写代码来组装咱们的「老八秘制小汉堡」了!!!
先是完善配置文件:config.ini
这里能够根据本身的习惯自定义在对应的区域,增长或者减小,动态配置~
在翻译脚本 AutoTranslate.py 的开头读取一波配置信息:
接着定义一个读取节点列表的方法:
再接着定义一个解析翻译结点内容的方法:
最后定义一个写入文件的方法:
接着花几分钟写个布局txt文件:
转换脚本调用下相关方法:
运行一波,能够看到生成了一个test.xml的布局文件,打开瞅瞅:
啧啧,格式化?
把xml复制到项目中,看看效果?
此处应该有掌声!啪啪啪!
脚本的大概雏形完成了,后面能够优化下交互和小细节,不过感受没技术含量?巧了,最近在 刷题,加个算法耍耍?来个LeetCode原题「有效的括号」,题目描述以下:
就是 匹配符号开闭,跟咱们这个场景很是类似哇,匹配开闭节点:
# 开闭节点须要一一对应,好比:+ cly- cly# 多了少了,都不行(以下两种都是错误的)+ cly+ cly- cly+ cly+ ly- cly- ly复制代码
怎么解决?最标准解法就是用 栈 了,比较简单,直接撸代码:
接着调用下:
故意写错结点,运行看看:
能够,大功告成~
久违的摸鱼闲暇时光,给你们作了一个老八秘制做小🍔,呸…