Flex箱型布局在移动端的应用

在平时开发过程中,用的最多的布局方式当然就是苹果自带的AutoLayout,但是使用的过程中也发现AutoLayout自身也有很多的问题。在我们的项目中,由于展现逻辑比较灵活,视觉每期的变化比较大,在使用过程中,很大一部分时间都在调整视觉中,所以想引入一个更简单的布局方式,这就是大名鼎鼎的Flex,也叫箱型布局。

首先来看看我们在AutoLayout中遇到的几个问题

AutoLayout自身的API简直反人类,所以大家使用过程中往往会引入第三方库(Masonry, PureLayout)。Masonry看上去更加直观,但是不太符合OC的编码习惯,PureLayout更符合OC的规范,使用起来也稍复杂点。两者都有很多的使用者。虽然第三方库简化了API,但并没有简化场景。

另一个AutoLayout令人诟病的问题,就是当视图增加的时候,计算复杂度成倍上升。AutoLayout依靠解线性方程组,所以越多的视图性能下降非常大。

在使用场景上,举几个例子。

|---- View1 ----|
|---- View2 ----|
|---- View3 ----|

如果要排上图3个View的时候,AutoLayout必须指定相互间的依赖。

如果仅仅如此还好解决,那么现在告诉你,View1可能是个1行或者2行的Label,那么如何平均分配之间的大小和间隔呢?

如果这样还是容易解决,那么再告诉你,View2可能是个没有内容的视图,当没有视图的时候1和3之间要保持之前的间距,这时候,不可能简单的解决了,必须修改依赖,一种方式是删除所有的AutoLayout,重新布局一遍,另外一种是保存AutoLayout实例,修改单个属性。无论如何,都不能避免修改依赖。

如果说到这里你都觉得轻松解决,那么下面这种呢

|       |---- View1 ----|         |         |
| Image |---- View2 ----| Action1 | Action1 |
|       |---- View3 ----|         |         |

这是标准的TableViewCell样式,但是如果说View和Action都是动态的,可能会被隐藏,但隐藏的时候不能空着一块,垂直的需要居中,水平的需要拉伸。这时候就彻底的蛋疼了,恰好我们的项目中就有很多类似的场景,由此我们很多时间都浪费在调整UI上,又容易漏掉场景导致一些视觉bug。

在一次次的UI修改中,我终于受不了了

在视觉排版这个从印刷术发明就存在的问题,到现在计算机领域,最成熟最靠谱的当然是Web技术,从互联网出现,到现在的响应式界面,web经历了历史的历练,从而产生了一套稳定靠谱的布局方式,而最新的就是不久前被加入标准的Flex布局(也可以称为Box布局)。

关于布局使用,有很多有名的介绍文章,我作为一个半吊子人士,就不做详细介绍了。简单来说,就是把每个视图都看作一个箱子,拥有内边距外边距,然后根据一定顺序排布下去,相互间不会产生依赖,当某个视图的属性display: none,自动忽略该视图。

比AutoLayout好的地方

首先,Flex计算简单,不会因为视图的增加性能急剧下降。

同时也可以方便的解决上述的几种场景,可以动态的根据视图来排版,而不需要相对的去设置,同时拉伸和挤压也很好控制(flex-grow, flex-shrink)。

甚至可以解决部分需要UITableView或者UICollectionView才比较好解决的问题。举个例子,微信九宫格图片,如果不是用UICollectionView来做,那么可能你需要保存9个实例,然后在layoutSubview里面做各种判断,计算frame,那简直是太恐怖了!看到这样的代码谁还有兴趣读下去吗。而使用UICollectionView则可以很好的解决布局问题,还能复用,但是很多场景下并不会产生复用,而使用UICollectionView又会新引入很多层视图层级和一些不需要的功能,虽然很好解决了问题,但并不是特别简单。那么这时候Flex布局的优势就特别明显了,只要flex-wrap属性就可以搞定一切。

总的来说,使用简单,学习成本低,性能也很不错,兼容性也高,这也是很多人为什么会嘲笑苹果自己搞了一套复杂无比的布局系统。

缺陷

Flex布局最大的缺陷就是视图层级的增加,每个箱子都是一个视图,看web的代码可以发现无数的div,单纯的为了实现一套布局。不过对于移动端来说,一个视图不会拥有太多的元素,可以说这个问题没有那么的严重。

我也在考虑是否可以创建一层virtual view,可以用来代替view作为箱型容器,或者把布局系统移除view作为容器这一web上的逻辑,分离布局和view。无论怎么样这两种方案都会增加复杂度。

同时,由于原生并不提供Flex支持,所以需要自己引入Flex库,并且需要在layoutSubview或者viewDidLayoutSubview中,手动触发计算。关于这个问题,可能自己创建系列Flex根控件比较好。

目前使用Flex的项目,或者类似的功能

现在最有名的方案是Facebook的Yoga,遗憾的是iOS端的YogaKit正处于开发阶段,可能不是那么的稳定。

正在使用Yoga的开源项目也有很多,有名的有AsyncDisplayKit, React Native, weex。所以从目前使用场景来看是没有什么问题的。

比较相似的功能其实早有方案,比如Android的LinearLayout和iOS的UIStackView,可以说这两者都是阉割版的Flex。

YogaKit

我们来看下YogaKit的一些API。不要问我为什么是swift,老外现在都在玩swift。

root.configureLayout { (layout) in
    layout.isEnabled = true
    layout.width = YGValue(containerSize.width)
    layout.height = YGValue(containerSize.height)
    layout.alignItems = .center
    layout.justifyContent = .center
}

如果是swift,将会非常简单,枚举的一半都被省略了,但是OC可能会稍微麻烦一点。API也是几乎参考的Masonry,重要的是,再也不会出现依赖了!!!感觉棒棒的。

同时Yoga不是完全的实现了Flex的功能,他是为移动端、客户端专门定制的布局系统,所以也有部分Flex没有的功能,也有部分Flex属性没有效果。

同时Yoga非常的精简,核心代码只有3000多行的c语言,引入成本也非常的低,所以决定在下一期实战型的使用下,来解决一直遗留的问题。

更多的考虑

在项目的过程中,作为程序员,都希望代码能够复用,提高稳定性。然而现实是残酷的,其他人并不会替你思考这些问题,所以就有很多场景,明明看着一模一样,但是某几个字体就是不一样,大小就是差那么几个像素。那么要处理这种问题,一般有两种方案。

1,继承,基类写基本成员,子类来写布局和属性。这样会导致很多子类,不熟悉的人会很疑惑这些东西都在哪里用的。

2,增加style属性,使用style来重写布局和属性,这样可能会随着类型的增多switch-case也增加。

同样,这里web也给了我们一个很好的思路。内容-样式分离,我们可以做一套类似于css的系统,使用class来设置布局样式,这样布局样式也可以复用了!

当然这个思路有部分人已经做好了开源库,css样式直接应用到控件。但是感觉没有那么完美,所以以后可以考虑下如何更好的把样式布局给统一到外部。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容