【发布时间】:2019-12-07 13:06:29
【问题描述】:
我需要创建一个视图层,该视图层由根据 api 响应布局的组件组成。
想象一下,我有一个类似的 JSON 响应 -
{
"id":"1fbcf51b-1811-405d-ba92-de5110910f83",
"name":"Gaming day",
"contentTemplate":{
"id":"300c01c3-747e-4446-8193-c2d633bfa8da",
"name":"Social Announcement",
"defaultLayoutId":"article",
"layouts":[
{
"id":"article",
"body":[
{
"classType":"CONTAINER",
"category":"CONTAINER",
"type":"FULL_WIDTH",
"elements":[
{
"classType":"TEXT",
"category":"INPUT",
"type":"TITLE",
"fieldId":"title"
},
{
"classType":"TEXT",
"category":"INPUT",
"type":"SUMMARY",
"fieldId":"subtitle"
},
{
"classType":"IMAGE",
"category":"INPUT",
"type":"IMAGE",
"fieldId":"mainImage"
},
{
"classType":"TEXT",
"category":"INPUT",
"type":"RICH_TEXT",
"fieldId":"body"
}
]
},
{
"classType":"CONTAINER",
"category":"CONTAINER",
"type":"TWO_COLUMN_GRID",
"elements":[
{
"classType":"IMAGE",
"category":"INPUT",
"type":"IMAGE",
"fieldId":"image1"
},
{
"classType":"TEXT",
"category":"INPUT",
"type":"RICH_TEXT",
"fieldId":"body1"
},
{
"classType":"TEXT",
"category":"INPUT",
"type":"RICH_TEXT",
"fieldId":"body2"
},
{
"classType":"IMAGE",
"category":"INPUT",
"type":"IMAGE",
"fieldId":"image2"
}
]
},
{
"classType":"CONTAINER",
"category":"CONTAINER",
"type":"FULL_WIDTH",
"elements":[
{
"classType":"METADATA",
"category":"METADATA",
"type":"RELATED_ARTICLES"
}
]
}
]
}
]
}
}
在这里您可以看到layouts 包含一个元素数组,所有类型都相同,有些具有更多可选属性,有些还具有嵌套元素。
它本质上描述了组件及其呈现方式
- 全宽行,堆叠 4 个元素
- 2 列网格,这些元素堆叠在两列中
- 全宽行,包含单个元素
这看起来像这样 -
这是一个示例,但其他布局将遵循此 JSON 结构。
在非常高的层次上,我将每个组件构建为UIView 的子类,并允许它接受各种模型,为显示的每个元素设置数据。它们都将符合LayoutComponent 协议并设置了一些标准值。在这一点上这很简单。
然后我将使用工厂为给定类型“构建”组件。
因为一切都将是UIView 的子类,所以我应该没问题。
目前我不确定的是如何处理组件之间的相互关系。每个组件的内部布局都很简单,因为我可以将元素锚定在我需要知道的位置,因为我知道每个组件中存在哪些元素。
在将这些元素的总和锚定到呈现 UIViewController 的 UIView 时,因为布局是动态的,我不知道如何告诉最后一个 FULL_WIDTH 元素锚定到底部,以及之前的元素锚定到它的底部到顶部等等。
如果感觉我可能最终会得到大量 if 语句和自动布局代码。
【问题讨论】:
-
您是否考虑过为每个“容器”元素使用
UIStackView?您可以根据数据中的一些道具设置其应如何呈现的属性,然后您无需担心锚定到顶级超级视图 -
绝对同意其他人的观点,UIStackView 是这样做的方法。这看起来像一个有趣的难题,所以如果我今天有时间并发布一个回购链接,我会修补它。
标签: swift uiview autolayout