制作一个类似苹果VFL的格式化语言来描述UIStackView
在项目中总是希望页面上各处的文字,颜色,字体大小甚至各个视图控件布局都能够在发版之后能够修改以弥补一些前期考虑不周,或者根据统计数据能够随时进行调整,当然是各个版本都能够统一变化。看到这样的要求后,第一反应是这样的页面只能改成H5,或者尝试使用React Native来应对这种要求。
既然UIStackView已经提供了一种既先进又简洁的布局思路,为何不通过制作一个类似VFL这样的DSL语言来处理布局。这样不就能够通过下发一串DSL字符串的方式来进行内容样式甚至布局的更换,不用跟版,还能使多版本统一。同时在端内直接用这样的DSL语言来写界面不光能够减少代码量易于维护,还能够很直观方便的看出整个界面布局结构。
AssembleView(组装视图)和PartView(零件视图)
在设计格式化语言之前需要对布局做个统一思想进行管理,在看了WWDC里关于UIStackView的介绍后感觉任何复杂的布局都能够通过这样一种组合排布再组合排布的思路特别适合用格式化语言来描述。于是我想出两个视图概念。
一个是AssembleView组合视图,专门用于对其PartView子视图进行排列,比如说是水平排列还是垂直排列,PartView是按照居中对齐还是居左等对齐方式,各个PartView之间间隔是多少。
PartView决定自己视图类型,内容,无固定大小的可以设置大小,同时AssembleView可以作为PartView被加入另一个AssembleView里进行排列,这样各种设计图都可以在初期通过拆解分成不同的AssembleView和PartView进行组合套组合布局出来。
格式化语言
接下来是如何通过格式化语言来描述AssembleView和PartView。“{}”符号里包含的是AssembleView的设置,“[]”符号里是PartView的设置,“()”里是他们的属性设置,“”可以将对象带入到设置里。下面举几个例子说明下。完整Demo放到了Github上:https://github.com/ming1016/STMAssembleView
三个星星水平对齐居中排列
h表示水平排列horizontal,c表示居中center,“[]”PartView会根据顺序依次添加排列,imageName属性能够指定本地图片
三个星星水平对齐居中排列
{
hc(padding:30)
[(imageName:starmingicon)]
[(imageName:starmingicon)]
[(imageName:starmingicon)]
}
AssembleView里套作为PartView的AssembleView的复杂情况
color可以指定文字颜色,font指定文字大小
AssembleView里套作为PartView的AssembleView的复杂情况
{
ht(padding:10)
[avatarImageView(imageName:avatar)]
[
{
vl(padding:10)
[(text:戴铭,color:AAA0A3)]
[(text:Starming站长,color:E3DEE0,font:13)]
[(text:喜欢画画编程和写小说,color:E3DEE0,font:13)]
}
(width:210,backColor:FAF8F9,backPaddingHorizontal:10,backPaddingVertical:10,radius:8)
]
}
给PartView设置背景色和按钮
设置背景色使用backColor,背景距离设置的PartView的内容间距通过backPaddingHorizontal属性设置水平间距,backPaddingVertical设置垂直间距,“”符号带入的button通过button属性设置。
[
{
hc(padding:4)
[(imageName:starmingicon,width:14,height:10)]
[(text:关注,font:16,color:FFFFFF)]
}
(height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:)
]
AssembleView设置忽略约束的方法
水平排列时,通过ignoreAlignment属性设置忽略left约束,如果是垂直排列设置top忽略。
{
hc(padding:5)
[(text:STMAssembleView演示,color:E3DEE0,font:13)]
[(imageName:starmingicon,width:14,height:10,ignoreAlignment:left)]
[(text:Starming星光社,color:E3DEE0,font:13)]
}
将前面的视图组合成一个AssembleView
将前面的视图组合成一个AssembleView
ASS(@"{
vc(padding:20)
[%@(height:90)]
[%@(height:36,backColor:AAA0A3,radius:8,backBorderWidth:1,backBorderColor:E3DEE0,backPaddingHorizontal:80,backPaddingVertical:10,button:)]
[%@(height:25)]
[%@(ignoreAlignment:top,isFill:1,height:16)]
}",midStr,followBtStr,centerStr,desStr)
AssembleView的属性
当在“{}”里面第一个字母是v表示垂直排列vertical,是h表示水平排列horizontal
第二个字母是c表示所有PartView居中对齐center,l表示居左对齐left,r表示居右对齐right,t表示居上对齐top,b表示居下对齐bottom。
padding:默认各个PartView的间距。
PartView的属性
如果不希望通过属性生成视图,可以通过在[后直接填入带入对象对应的key,然后再在()里设置属性。
PartView布局相关属性
width:UILabel和UIImage这样有固定大小的可以不用设置,会按照固定大小的来。
height:有固定大小的可以不用设置。
isFill:垂直排列时会将宽设置为父AssembleView的宽,水平排列时会将高设置为父AssembleView的高。
padding:设置后会忽略父AssembleView里设置的padding,达到自定义间距的效果。
partAlignment:可以自定义对齐方向,设置后会忽略父AssembleView里设置的对齐。值可填center,left,right,top,bottom。
ignoreAlignment:设置忽略的约束方向,在父AssembleView不需要由子PartView决定大小的情况下,可以通过打断某个方向约束来实现拆开排列的效果。值可填center,left,right,top,bottom。
PartView权重相关属性
crp:Compression Resistance Priority的设置,根据权重由低到高值可以设置为fit,low,high,required。对应的UILayoutPriority的分别是UILayoutPriorityFittingSizeLevel,UILayoutPriorityDefaultLow,UILayoutPriorityDefaultHigh,UILayoutPriorityRequired。
minWidth:对应NSLayoutRelationGreaterThanOrEqual,设置一个最小的宽
maxWidth:对应NSLayoutRelationLessThanOrEqual,设置一个最大的宽
PartView视图控件相关设置
通过以下属性即可生成对应的UILabel,UIImageView或者UIButton等控件视图,而不用特别指出需要生成哪种控件视图
text:设置文字内容
font:设置字体,可以带入一个UIFont,也可以直接设置一个字体大小,解析时会判断类型。
color:设置颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。
imageName:设置本地图片,值是本地图片名称。
image:带入一个UIImage。
imageUrl:设置一个网络图片的url地址,ps:目前需要通过来带入一个字符串。
PartView的通用设置
可以为PartView创建一个底部视图,并设置其样式。也可以添加一个UIButton设置UIControlStateHighlighted时的样式。
backColor:设置底部视图的颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。
backPaddingHorizontal:设置当前PartView视图距离底部视图top和bottom的间距。
backPaddingVertical:设置当前PartView视图距离底部视图left和right的间距。
backBorderColor:设置底部视图边框的颜色,可以带入一个UIColor,也可以直接设置一个十六进制颜色,解析时会判断类型。
backBorderWidth:设置底部视图边框宽。
radius:设置底部视图的圆角半径。
button:带入一个button。
buttonHighlightColor:设置button在UIControlStateHighlighted时的颜色,默认是透明度0.05的黑色。
解析格式化语言
解析过程的第一步采用扫描scanner程序将字符串按照分析符号表将字符流序列收集到有意义的单元中。
第二步将这些单元逐个归类到对应的类别中。比如解析到“()”里内容时就将其归类到对应的AssembleView的属性或者PartView的属性类别中。在归类过程中会出现PartView是AssembleView,这个Assemble里面又有这样作为PartView的AssembleView这样层层套的情况,所以需要采用类似引用计数方式保证在最后一个“}”符号结束时能将整个Assemble递归进行解析。
第三步将各个类别集合转换成对应原生代码从而生成对应的视图布局。
具体实现可以查看STMAssembleView.m文件。Github地址:https://github.com/ming1016/STMAssembleView
如何生成页面
生成页面需要实现格式化语言对应的原生代码,所有PartView的属性都会存放在STMPartMaker里,包括带入的自定义视图还有用于生成视图控件的属性等。PartView属性设置完成后会在STMPartView这个类中先决定对应的视图控件,并将STMPartMaker里的属性都设置上。实现代码可以查看STMPartView.m里的- (STMPartView *)buildPartView方法。
接下来STMAssembleView会在buildAssembleView时进行布局,具体实现代码可以查看STMAssembleView.m里的- (STMAssembleView *)buildAssembleView方法。
制作一个类似苹果VFL的格式化语言来描述UIStackView的更多相关文章
- 如何制作一个类似Tiny Wings的游戏(2) Cocos2d-x 2.1.4
在第二篇<如何制作一个类似Tiny Wings的游戏>基础上,增加添加主角,并且使用Box2D来模拟主角移动,原文<How To Create A Game Like Tiny Wi ...
- 如何制作一个类似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇<如何使用CCRenderTexture创建动态纹理>基础上,增加创建动态山丘,原文<How To Create A Game Like Tiny Wings with Co ...
- 如何制作一个类似jquery插件的vue插件
vue拿来写插件,会不会太那啥? 请跟我念,"不会,符合业务需求才是你的老板最想要的." 如何封装一个可以全局调用的vue插件 其原理其实相当简单,通过new Vue(vueCom ...
- 怎样制作一个相似Tiny Wings的游戏 Cocos2d-x 2.1.4
在第一篇<怎样使用CCRenderTexture创建动态纹理>基础上,添加�创建动态山丘,原文<How To Create A Game Like Tiny Wings with C ...
- Swift 中使用 SwiftyJSON 制作一个比特币价格 APP
Swift 中处理 JSON 数据有很多种方式,可以使用原生的 NSJSONSerialization,也可以使用很多第三方库.原生的 NSJSONSerialization 方式这篇文章中介绍过.这 ...
- 使用CocosSharp制作一个游戏 - CocosSharp中文教程
注:本教程翻译自官方<Walkthrough - Building a game with CocosSharp>,官方教程有很多地方说的不够详细,或者代码不全,导致无法继续,本人在看了G ...
- Swift 制作一个新闻通知中心插件1
使用 Swift 制作一个新闻通知中心插件(1) 随着 iOS 8 的发布,苹果为开发者们开放了很多新的 API,而在这些开放的接口中 通知中心插件 无疑是最显眼的一个.通知中心就不用过多介绍了,相信 ...
- TensorFlow练习13: 制作一个简单的聊天机器人
现在很多卖货公司都使用聊天机器人充当客服人员,许多科技巨头也纷纷推出各自的聊天助手,如苹果Siri.Google Now.Amazon Alexa.微软小冰等等.前不久有一个视频比较了Google N ...
- 制作一个64M的U盘启动盘(mini linux + winpe +dos toolbox)
制作一个64M的U盘启动盘(mini linux + winpe +dos toolbox) 自己动手定制winpe+各类dos工具箱U盘启动盘+minilinux 由于一个64M老U盘,没什么用,拿 ...
随机推荐
- C++构造函数,复制构造函数和析构函数专题
链接:http://wenku.baidu.com/view/d9316c0e52ea551810a6872a.html 本文作者:黄邦勇帅本文是学习 C++中的最基本的内容,因此学习 C++就应全部 ...
- prim(与边无关,适合稠密的图,o(n^2))---还是畅通工程
题目1017:还是畅通工程 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1653 解决:838 题目描述: 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府“ ...
- c++模板实现抽象工厂
类似于rime的rime::Class<factory type, product type>实现方式. C++模板实现的通用工厂方法模式 1.工厂方法(Factory Method)模式 ...
- PHP FTP上传文件
第一步:建立一个新的 FTP 连接. ftp_connect(host,port,timeout); host必需,规定要连接的 FTP 服务器,可以是域名或 IP 地址,后面不应以斜线结 ...
- FORM Save : ORA-01403 FRM-40735 ORA-06502
症状: FORM开发后挂上服务器后,运行保存按键提示: ORA-01403: 未找到任何数据 ----------------------------------------------------- ...
- 理解Java ClassLoader机制
当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初始类加载器层次结构: bootstrap classloader | extension cla ...
- Linux -- Ubuntu搭建java开发环境
Steps 1 Check to see if your Ubuntu Linux operating system architecture is 32-bit or 64-bit, open up ...
- Response.Write用法总结
问题一: Response.Write 后连接Response.Redirect ,则Response.Write无法显示,直接跳转入Response.Redirect 的页面. 解决方案: Resp ...
- 用excel打造报表查询系统
网络数据库以及ERP在中小型企业中日益风行,虽然ERP功能强大,但有的ERP报表系统中规范的报表较少,主要提供二次开发接口或通过如CRYSTALREPORT等其他报表工具进行管理,其实我们可以使用Ex ...
- C#实现Zip压缩解压实例【转】
本文只列举一个压缩帮助类,使用的是有要添加一个dll引用ICSharpCode.SharpZipLib.dll[下载地址]. 另外说明一下的是,这个类压缩格式是ZIP的,所以文件的后缀写成 .zip. ...