使用视图作为另一个视图的参数,而不使用 AnyView

huangapple go评论66阅读模式
英文:

Using Views as parameters for another View without AnyView

问题

View1

结构体 View1: View {
    let title: String
    let text: String

    var body: some View {
        HStack {
            Text(title)
            Text(text).bold()
        }
    }
}

View2

结构体 View2: View {
    let title: String
    let text: String

    var body: some View {
        HStack {
            Text(title).bold()
            Text(text)
        }
    }
}

ParameterView - 目前传递的 view 参数被包装在 AnyView() 中。

结构体 ParameterView: View {
    let title: String
    let view: any View

    var body: some View {
        HStack {
            Text(title)
            AnyView(view)
        }
    }
}

In practice:

结构体 ParameterView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            ParameterView(
                title: "Noodles",
                view: View1(title: "£", text: "1.00")
            ) // Noodles £ 1.00

            ParameterView(
                title: "Mass",
                view: View2(title: "100", text: "g")
            ) // Mass 100 g
        }
    }
}
英文:

I have two views that I want to use as possible parameters in another view. I've been using AnyView, but would much rather use @ViewBuilder instead; I'm not 100% sure on how to implement this though.
See below:

View1

struct View1: View {
    let title: String
    let text: String

    var body: some View {
        HStack {
            Text(title)
            Text(text).bold()
        }
    }
}

View 2

struct View2: View {
    let title: String
    let text: String

    var body: some View {
        HStack {
            Text(title).bold()
            Text(text)
        }
    }
}

ParameterView - currently the view parameter being passed through is being wrapped in AnyView().

struct ParameterView: View {
    let title: String
    let view: any View

    var body: some View {
        HStack {
            Text(title)
            AnyView(view)
        }
    }
}

In practice:

struct ParameterView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            ParameterView(
                title: "Noodles",
                view: View1(title: "£", text: "1.00")
            ) // Noodles £ 1.00

            ParameterView(
                title: "Mass",
                view: View2(title: "100", text: "g")
            ) // Mass 100 g
        }
    }
}

答案1

得分: 1

你沿着正确的方向 - 使用 @ViewBuilder 是正确的方法!我们将与泛型一起使用它。我将以你的 ParameterView 为例:

struct ParameterView<Content: View>: View {
    let title: String
    @ViewBuilder let view: Content

    var body: some View {
        HStack {
            Text(title)
            view
        }
    }
}

在这里,我们创建了一个视图,它使用泛型类型 Content,它必须符合 View。我们使用 @ViewBuilder 属性包装器,它基本上表示我们的属性 view 是一个将返回类型为 Content 的属性的函数,并且因为 Content: View,所以我们可以像对待任何 View 一样使用这个属性。然后,剩下的就是在 body 中使用它。

这是用法:

struct UsageView: View {
    var body: some View {
        ParameterView(title: "Noodles") {
            View1(title: "£", text: "1.00")
        }
    }
}

请注意,我在这里使用了尾随闭包语法,因为 @ViewBuilder 将我们的属性转换为方法。

英文:

You're along the right lines - using @ViewBuilder is the way to go! We will combine this with the use of generics. I'll use your ParameterView as an example:

struct ParameterView&lt;Content: View&gt;: View {
    let title: String
    @ViewBuilder let view: Content

    var body: some View {
        HStack {
            Text(title)
            view
        }
    }
}

Here we're creating a view that uses a generic type Content that must conform to View. We use the @ViewBuilder property wrapper that basically says our property view is some function that will return a property of type Content and because Content: View we can use this property as we can with any View. Then all that's left to do is use that within the body.

Here's the usage:

struct UsageView: View {
    var body: some View {
        ParameterView(title: &quot;Noodles&quot;) {
            View1(title: &quot;&#163;&quot;, text: &quot;1.00&quot;)
        }
    }
}

Note that I'm using trailing closure syntax here because @ViewBuilder turns our property into a method.

huangapple
  • 本文由 发表于 2023年2月23日 23:38:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75547044.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定