自定义“列表”视图

时间:2019-07-12 16:22:23

标签: swift swiftui

在SwiftUI中,const_cast将自动设置您传递它的子视图的格式,如下所示:

List

将导致两个文本视图正确放置,并在它们之间使用分隔符等。

此外,还可以混合使用静态和动态生成的数据,如下所示:

List {
  Text("A")
  Text("B")
}

我的目标是编写自己的自定义类型,以允许其用户进行这种使用(即:一种视图,该视图可让用户使用新的功能构建器DSL提供视图,而无需他们编写自己的修饰符来放置它们显示在屏幕上),但我根本不知道要在自定义视图的初始化程序中添加什么内容。

本机SwiftUI视图使用List { Text("A") ForEach(foo) { fooElement in CustomView(fooElement) } Text("B") ForEach(bar) { barElement in CustomView(barElement) } } 并接收符合@ViewBuilder的通用类型,但是它们能够提取元素(例如,从View视图)是神秘的,我非常确定这是不可能的。

也许我错过了一些事情,所以很好奇您对此有何看法?

编辑: 一个例子可能更清楚。你们中的许多人肯定在网上看到了不错的示例,其中的卡片使用ForEach并排放置,所以如果我想创建一个ZSack类型的类型,该类型将允许我的用户编写这样的代码怎么办? ?

CardStack

这将导致12张卡片彼此堆叠,请注意,这些类型不是同质的,我们使用了CardStack { SomeView() AnotherView() ForEach(1...10) { i in NumberView(i) } }

1 个答案:

答案 0 :(得分:0)

挑战的第一步是弄清楚ViewBuilder。关于从儿童到祖先的数据流,请继续阅读:

通过使用首选项(请参阅我的文章https://swiftui-lab.com/communicating-with-the-view-tree-part-1/),您可以使信息从孩子流向祖先。

一旦您完全理解了首选项并使它们生效,您可以尝试使实现更加清晰透明,这样您的Stack的最终用户甚至不会意识到自己正在使用首选项。为此,您可以使用一些View扩展。最终的代码可能如下所示:

CardStack {
   SomeView().card(title: "", border: .red)
   AnotherView().card(title: "", border: .green)

  ForEach(items) { item in
    NumberView(item).card(item.name, border: .blue)
  }
}

您的.card()实现可能是这样的:

extension View {
   func card(title: String, border: Color) -> CardCustomizer<Self> {
       return CardCustomizer(viewContent: self, title: title, border: border)
   }
}

struct CardCustomizer<Content: View>: View {
    public let viewContent: Content
    public let title: String
    public let border: Color

    var body: some View {
        viewContent.preference(MyCardPref.self, value: ...)
    }
}

我认为最好是先尝试使它在没有View扩展的情况下工作,这样一来您就正确了。然后继续用扩展封装首选项逻辑。否则,有太多新事物要处理。