【问题标题】:Anchoring UI elements based on a JSON response基于 JSON 响应锚定 UI 元素
【发布时间】: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 包含一个元素数组,所有类型都相同,有些具有更多可选属性,有些还具有嵌套元素。

它本质上描述了组件及其呈现方式

  1. 全宽行,堆叠 4 个元素
  2. 2 列网格,这些元素堆叠在两列中
  3. 全宽行,包含单个元素

这看起来像这样 -

这是一个示例,但其他布局将遵循此 JSON 结构。

在非常高的层次上,我将每个组件构建为UIView 的子类,并允许它接受各种模型,为显示的每个元素设置数据。它们都将符合LayoutComponent 协议并设置了一些标准值。在这一点上这很简单。

然后我将使用工厂为给定类型“构建”组件。

因为一切都将是UIView 的子类,所以我应该没问题。

目前我不确定的是如何处理组件之间的相互关系。每个组件的内部布局都很简单,因为我可以将元素锚定在我需要知道的位置,因为我知道每个组件中存在哪些元素。

在将这些元素的总和锚定到呈现 UIViewControllerUIView 时,因为布局是动态的,我不知道如何告诉最后一个 FULL_WIDTH 元素锚定到底部,以及之前的元素锚定到它的底部到顶部等等。

如果感觉我可能最终会得到大量 if 语句和自动布局代码。

【问题讨论】:

  • 您是否考虑过为每个“容器”元素使用UIStackView?您可以根据数据中的一些道具设置其应如何呈现的属性,然后您无需担心锚定到顶级超级视图
  • 绝对同意其他人的观点,UIStackView 是这样做的方法。这看起来像一个有趣的难题,所以如果我今天有时间并发布一个回购链接,我会修补它。

标签: swift uiview autolayout


【解决方案1】:

UIStackView 会为您执行此操作,只要每个子元素都具有固有的内容大小或堆栈方向的约束(水平堆栈的宽度和垂直堆栈的高度)。

整个东西应该是一个垂直的stackview,每一行应该是一个水平的stackview。如果您认为它会比屏幕大,则将其放入滚动视图中,并将垂直堆栈锚定到 contentLayoutGuide,宽度约束等于 scrollViews 父级;然后它只会垂直滚动,因为它太大而无法显示。

Apple 的 stackview 指南:https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

【讨论】:

    【解决方案2】:

    我建议您使用 UICollectionView 来完成此任务。 该类实现了单元格的复用,在显示列表时不会消耗大量内存

    您需要像 ImageCell、TextCell 和其他元素这样的单元格。此单元格应绘制指定大小的内容(使用 sizeThatFits 和 layoutSubviews 或自动布局)

    为了实现一些布局规则,您有两种可能的方法:

    1) 创建自定义 UICollectionViewLayout,doc from Apple

    2) 另一种方法是创建布局单元格,如 TwoColumnCell、FullWidthCell。并添加元素单元格,如用于布局单元格的子视图。

    第二种方式破坏了重用单元格,因为您不能将单元格重用于具体元素类型。 而且你可以基于 UIView 来实现这种方式,而不是 UICollectionView。想法是有很少的单元格用于布局和很少的单元格用于绘制内容的类

    【讨论】:

      猜你喜欢
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2012-10-30
      • 2018-08-18
      • 2022-01-11
      • 2021-04-09
      • 1970-01-01
      相关资源
      最近更新 更多