前言
在app开发中,我们可能会有这样的需求,页面中的某个布局像表格一样,但必须支持动态修改布局。以值得买为例,如下图:
红框区域布局可能需要动态改变,比如我今天显示8个item,明天可能只显示4个item,但是布局都是规则的矩形块。这个要怎么实现呢?
在我们的项目中也有类似的需求,一开始我们是采用WebView去实现,但是WebView毕竟比较重,能用原生实现的当然尽量要用原生去实现。
我苦思冥想,想到了一个另类的实现方式。先看效果:
思路
一般的开发中,json数据只表示内容,不表示布局。而html既表示内容,同时也表示布局,这样html较json数据能表示更丰富的元素,也就是html更加灵活,显示啥完全由服务端控制,当然这样也带来了数据冗余,而且通过html绚烂布局也是比较消耗性能的。
能不能让json既表示内容,又表示布局呢?
当然是可以的,只要服务端和客户端约定某种规则,把布局的相关内容写到json数据中就行,然后客户端遵循相应规则去显示就行。这样用json数据也就能够动态的修改布局了。这也是我实现动态栅格布局的整体思路。
还是以值得买为例。服务端必须告诉客户端该如何显示:一共有几行,每一行该怎么分割。比如把一行分割成两个小块,然后小块里面还可以继续分割。这些信息,是通过json数据来表示的。
以上图为例:
1. 整体分为两行。第一行,分割成两个小块A,B,小块的排列顺序为水平方向,比例为2:3。
* A 小块显示图片a。
* B 小块分割为B1和B2。
* B1 显示图片b1
* B2 继续分割为D和E。排列方向为水平。依此类推。
2. 第二行,分割为4个小块,排列顺序为水平方向,比例为1:1:1:1。
数据结构如下:
{
"images": [
{
"children": [
{
"image": "https://xxxx.png",
"weight": 2
},
{
"children": [
{
"image": "https://xxxx.png",
"weight": 1
},
{
"children": [
{
"image": "https://xxxx.png",
"weight": 1 },
{
"image": "https://xxxx.png",
"weight": 1 }
],
"orientation": "h",
"weight": 1
}
],
"orientation": "v",
"weight": 3
}
],
"height": 312,
"orientation": "h"
},
{
"children": [
{
"image": "https://xxxx.png",
"weight": 1
},
{
"image": "https://xxxx.png",
"weight": 1
},
{
"image": "https://xxxx.png",
"weight": 1
},
{
"image": "https://xxxx.png",
"weight": 1
}
],
"height": 238,
"orientation": "h"
}
]
}
数据结构说明: images
是一个数组,每个元素表示一行。 children
是一个数组,每个元素表示一个小块。如果为null,直接显示图片。否则表示当前小块需要继续分割。客户端需要递归取出children里面的值来做分割(children里面还有children),直到children为null。行是一个特殊的块,它多了一个属性height
height
表示一行的高度。(这里的高度是基于设计稿的,还需要根据分辨率计算最终高度). orientation
表示小块里的子块的排列顺序。v
表示垂直,h
表示水平。 weight
表示这一小块占据的权重(比例)。 json
层级较深,wtf.
其他
当然,这个方案也有一定的局限性,但是我觉得最重要的是思路。只要客户端和服务端定制某个规则,其实json数据也是可以同时表示内容和布局的,这样就达到动态控制布局的目的。如果采用xml来实现的话,还有点定制html规范的感觉。
另外,想看iOS版实现的可以看iOS一种动态栅格布局方案。这是我同事写的,当我告诉他这个思路后,立马领悟了其中的精华并写了个demo。