iOS一种动态栅格布局方案

前言

在日常开发过程中,我们会遇到一些需要不定期动态改变布局的页面或视图块,下面用张图展示一下:

zdm_home.png

我以这张图解释一下需求,图上的几块都是需要显示不同的功能模块,点击的时候也需要跳转到不同页面。这个布局实现很简单,但是如果这个布局需要不定期的更改,比如A换到右边,大小发生变化等不确定因素,我们不可能就发布一个新的版本去修改这个页面。所以大部分人会选择webView来实现,或者事先约定好几种布局格式,由后台来随时改变布局。

解决思路

事实上这一块并占不了整个页面,大部分情况下只是在tableView中嵌套一截这样的需求,我公司项目的实现用的一直是webView来实现,但是这样就会有很多不必要的问题,比如webView的高度计算,如果客户端来计算高度,在一些网络不稳定情况下,webView的资源没有加载完全,高度就会出现偏差,而且webView的加载速度,性能,和js的交互都是很不理想的。(总之,我大原生就是不爱用h5啦)
这里其实有两种解决方案

  • 方案1:和后台约定好几种布局样式,客户端根据后台参数来动态显示。
  • 方案2:这块视图看为一个整体,根据json数据将其分为X个子块,理论上可以根据数据无限分割下去。

优缺点
第一种方案实现简单,而且可以应付日常所需,但是提前约定的格式必定不会太多,不够灵活。
第二种方案完全根据数据决定布局,子块可以无限分割下去,布局灵活,但是数据比较复杂。
实际上第二种布局是最近公司安卓小哥想出来 一个思路,我和他分别实现了一下,发现效果很好。这里是安卓小哥的简书

具体实现

下面来和大家说一下具体的实现思路:

zdm_home.png

我们还是以这张图为例:
1、我们首先定义两个rowitem元素,分别对应行和块的概念。如上图分为两行,A那里代表一整行,下面的四小块代表一整行。分割为row1row2
2、row1:分割为AB两块,水平排列,宽度比2:3

  • A不用再分,直接显示图片
  • B分为B1、B2两块,垂直排列,高度比1:1
  • B2分为D、E两块,水平排列,宽度比1:1
    row2:分割为1:1:1:1的四小块

json数据的结构如下:

{
    "images": [
        {
            "children": [
                {
                    "image": "https://i.huim.com/miaoquan/14966511524892.SS2!/both/300x300/unsharp/true",
                    "weight": 2
                },
                {
                    "children": [
                        {
                            "image": "https://i.huim.com/miaoquan/14963170206106.jpg!/both/300x300/unsharp/true",
                            "weight": 1
                        },
                        {
                            "children": [
                                {
                                    "image": "https://i.huim.com/miaoquan/14968041079523.jpg!/compress/true/both/300x300",
                                    "weight": 1
                                },
                                {
                                    "image": "https://i.huim.com/miaoquan/14968026112335.jpg!/compress/true/both/300x300",
                                    "weight": 1
                                }
                            ],
                            "orientation": "h",
                            "weight": 1
                        }
                    ],
                    "orientation": "v",
                    "weight": 3
                }
            ],
            "height": 212,
            "orientation": "h"
        },
        {
            "children": [
                {
                    "image": "https://i.huim.com/miaoquan/14929203253142.SS2!/both/300x300/unsharp/true",
                    "weight": 1
                },
                {
                    "image": "https://i.huim.com/contents/14828912708690.jpg!/both/300x300/unsharp/true",
                    "weight": 1
                },
                {
                    "image": "https://i.huim.com/miaoquan/14968146185109.jpg!/both/300x300/unsharp/true",
                    "weight": 1
                },
                {
                    "image": "https://i.huim.com/miaoquan/14968145059484.jpg!/both/300x300/unsharp/true",
                    "weight": 1
                }
            ],
            "height": 138,
            "orientation": "h"
        }
    ]
}

数据说明:
images:数组,数组的元素个数决定了整个View需要分为几行row
children:数组,数组元素个数决定了每个row需要分为多少个块item
heightrow的高度
orientation:布局方向,vh,分别对应垂直和水平方向
image:该子块显示的图片
weight:在这一块中的权重比

最重要的是对这个数据的处理,children代表了块,这里用到了递归的思想,只要这一层的数据有children,就需要一直分割下去,直到children为null,停止分割,显示图片。这里的数据层次较深,逻辑需要处理清晰。

不得不说,安卓小哥的当时提出了这个思路吸引到了我,和他分别实现了过后发现十分好用。这刚好解决了我公司项目中遇到的问题,如果衍生出去,其实可以代替很多地方的布局方式。这种布局灵活度很高,完全由后端数据控制,是个很棒的想法。

下面展示一下我实现的效果图:

FSGridLayoutDemo.gif

上面的边框线是我方便区分每一块加上的,实际开发可以忽略。若果需要每个子块的跳转信息,可以在image那一层加一个参数。比如我公司是定义了一个页面跳转协议,客户端,前端,后端都是遵循这个协议,我举个例子,加了一个跳转参数"pushurl":"huim://detail?id=1234",我就知道这块需要跳转到商品id为1234的详情页。实现了高度动态化布局和跳转。我也不知道该称之为什么布局,所以暂时称之为栅格化布局

局限性

这个布局正如我文章所述,一般是用来实现那种轻量级的页面,我主要是用来替代那种嵌套的webView的,如果太过复杂的页面当然就没有这个必要了。当然可以衍生出去可能会有适合你自己项目的地方。所以,酌情使用吧。

我写的demo在这里,想要看具体实现的可以前往下载,欢迎提出更好的实现方式。

如果对你有所帮助和启发,不妨点个喜欢

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

推荐阅读更多精彩内容