iOS一种动态栅格布局方案
前言
在日常开发过程中,我们会遇到一些需要不定期动态改变布局的页面或视图块,下面用张图展示一下:
zdm_home.png
我以这张图解释一下需求,图上的几块都是需要显示不同的功能模块,点击的时候也需要跳转到不同页面。这个布局实现很简单,但是如果这个布局需要不定期的更改,比如A换到右边,大小发生变化等不确定因素,我们不可能就发布一个新的版本去修改这个页面。所以大部分人会选择webView来实现,或者事先约定好几种布局格式,由后台来随时改变布局。
解决思路
事实上这一块并占不了整个页面,大部分情况下只是在tableView中嵌套一截这样的需求,我公司项目的实现用的一直是webView来实现,但是这样就会有很多不必要的问题,比如webView的高度计算,如果客户端来计算高度,在一些网络不稳定情况下,webView的资源没有加载完全,高度就会出现偏差,而且webView的加载速度,性能,和js的交互都是很不理想的。(总之,我大原生就是不爱用h5啦)
这里其实有两种解决方案:
方案1:和后台约定好几种布局样式,客户端根据后台参数来动态显示。
方案2:这块视图看为一个整体,根据json数据将其分为X个子块,理论上可以根据数据无限分割下去。
优缺点:
第一种方案实现简单,而且可以应付日常所需,但是提前约定的格式必定不会太多,不够灵活。
第二种方案完全根据数据决定布局,子块可以无限分割下去,布局灵活,但是数据比较复杂。
实际上第二种布局是最近公司安卓小哥想出来 一个思路,我和他分别实现了一下,发现效果很好。这里是安卓小哥的简书。
具体实现
下面来和大家说一下具体的实现思路:
zdm_home.png
我们还是以这张图为例:
1、我们首先定义两个row和item元素,分别对应行和块的概念。如上图分为两行,A那里代表一整行,下面的四小块代表一整行。分割为row1和row2。
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
height:row的高度
orientation:布局方向,v和h,分别对应垂直和水平方向
image:该子块显示的图片
weight:在这一块中的权重比
最重要的是对这个数据的处理,children代表了块,这里用到了递归的思想,只要这一层的数据有children,就需要一直分割下去,直到children为null,停止分割,显示图片。这里的数据层次较深,逻辑需要处理清晰。
不得不说,安卓小哥的当时提出了这个思路吸引到了我,和他分别实现了过后发现十分好用。这刚好解决了我公司项目中遇到的问题,如果衍生出去,其实可以代替很多地方的布局方式。这种布局灵活度很高,完全由后端数据控制,是个很棒的想法。
下面展示一下我实现的效果图:
FSGridLayoutDemo.gif
上面的边框线是我方便区分每一块加上的,实际开发可以忽略。若果需要每个子块的跳转信息,可以在image那一层加一个参数。比如我公司是定义了一个页面跳转协议,客户端,前端,后端都是遵循这个协议,我举个例子,加了一个跳转参数"pushurl":"huim://detail?id=1234",我就知道这块需要跳转到商品id为1234的详情页。实现了高度动态化布局和跳转。我也不知道该称之为什么布局,所以暂时称之为栅格化布局。
局限性
这个布局正如我文章所述,一般是用来实现那种轻量级的页面,我主要是用来替代那种嵌套的webView的,如果太过复杂的页面当然就没有这个必要了。当然可以衍生出去可能会有适合你自己项目的地方。所以,酌情使用吧。
我写的demo在这里,想要看具体实现的可以前往下载,欢迎提出更好的实现方式。
作者:PURE蓝胖子
链接:http://www.jianshu.com/p/a728ae289d0d
- 小程序组件化框架 WePY 在性能调优上做出的探究
- go sync.Mutex 设计思想与演化过程 (一)
- HTTPS 原理浅析及其在 Android 中的使用
- Bugly 多渠道热更新解决方案
- Go发起Http请求及获取相关参数
- Swift 对象内存模型探究(一)
- 关于 Block 中捕获 self 的分析
- go语言base64加密解密的方法
- Android 减包 - 减少APK大小
- Android 插件技术实战总结
- Golang语言社区--【基础知识】常量
- Android GC 原理探究
- 舞动的表情包——浅析GIF格式图片的存储和压缩
- go语言的官方包sync.Pool的实现原理和适用场景
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- LeetCode86|只出现一次的数字II
- LeetCode85|只出现一次的数字III
- LeetCode84|只出现一次的数字
- LeetCode83|排序矩阵查找
- LeetCode82|翻转字符串里的单词
- LeetCode81|移动零
- LeetCode80|反转字符串中的元音字母
- LeetCode79|平方数之和
- LeetCode91|寻找重复数
- LeetCode90|两个数组的交集
- LeetCode89|在排序数组中查找数字I
- LeetCode88|两数之和IV-输入BST
- LeetCode98|判定字符是否唯一
- LeetCode97|合并两个有序链表
- LeetCode99|数组中出现次数超过一半的数字