SwiftUI - 可重用组件,带有指向其他视图的链接作为参数
SwiftUI - reusable components with links to other views as parameters
我想在我的应用程序中创建可重用的组件。
我搜索过类似的问题。但我只找到了更复杂的例子。
让我们试试这个简单的例子——一个可以根据传递的参数打开不同视图的按钮。
我有 2 个视图,我将以 sheet:
打开
FirstView.swift
import SwiftUI
struct FirstView: View {
var body: some View {
Text("First view")
}
}
SecondView.swift
struct SecondView: View {
var body: some View {
Text("Second view")
}
}
ButtonView.swift
这是我想在我的设计系统中用作可重用组件的视图。
import SwiftUI
struct ButtonView: View {
@State private var showModal: Bool = false
// This works
var text: String
// Here I am getting an error:
// Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
var link: View
var body: some View {
VStack {
Spacer()
Button(action: {
self.showModal = true
}) {
Text(text)
.padding(20)
.foregroundColor(Color.white)
}.sheet(isPresented: self.$showModal) {
link
}
.background(Color.blue)
}
}
}
struct ButtonView_Previews: PreviewProvider {
static var previews: some View {
ButtonView(text: "TEST", link: FirstView())
}
}
ContentView.swift 这里我尝试使用相同的按钮组件,但标签和链接不同。
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
ButtonView(text: "first", link: FirstView())
.padding()
ButtonView(text: "second", link: SecondView())
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
传递字符串参数有效。标签不同。但我不能让它与不同视图的链接一起使用。我收到一个错误:
Protocol 'View' can only be used as a generic constraint because it
has Self or associated type requirements
保持第一个视图和第二个视图相同,对 ButtonView 使用以下内容:
struct ButtonView<Content : View>: View {
@State private var showModal: Bool = false
var text: String
// This is the generic content parameter
let content: Content
init(text: String, @ViewBuilder contentBuilder: () -> Content){
self.text = text
self.content = contentBuilder()
}
var body: some View {
VStack {
Spacer()
Button(action: {
self.showModal = true
}) {
Text(text)
.padding(20)
.foregroundColor(Color.white)
}.sheet(isPresented: self.$showModal) {
content
}
.background(Color.blue)
}
}
}
此处名为 content 的通用参数用于接收任何视图,初始化程序与 @ViewBuilder 属性 包装器一起使用以构建 view.Now 在 ContentView 结构中按以下方式使用它:
struct ContentView: View {
var body: some View {
HStack {
ButtonView(text: "First") {
FirstView()
}
ButtonView(text: "Second") {
SecondView()
}
}
}
}
它会很有魅力:)
此外,如果您想保留 ButtonView 的预览并且不希望它崩溃,请将预览添加为:
struct ButtonView_Previews: PreviewProvider {
static var previews: some View {
ButtonView(text: "First") {
FirstView()
}
}
}
我想在我的应用程序中创建可重用的组件。
我搜索过类似的问题。但我只找到了更复杂的例子。
让我们试试这个简单的例子——一个可以根据传递的参数打开不同视图的按钮。 我有 2 个视图,我将以 sheet:
打开FirstView.swift
import SwiftUI
struct FirstView: View {
var body: some View {
Text("First view")
}
}
SecondView.swift
struct SecondView: View {
var body: some View {
Text("Second view")
}
}
ButtonView.swift 这是我想在我的设计系统中用作可重用组件的视图。
import SwiftUI
struct ButtonView: View {
@State private var showModal: Bool = false
// This works
var text: String
// Here I am getting an error:
// Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
var link: View
var body: some View {
VStack {
Spacer()
Button(action: {
self.showModal = true
}) {
Text(text)
.padding(20)
.foregroundColor(Color.white)
}.sheet(isPresented: self.$showModal) {
link
}
.background(Color.blue)
}
}
}
struct ButtonView_Previews: PreviewProvider {
static var previews: some View {
ButtonView(text: "TEST", link: FirstView())
}
}
ContentView.swift 这里我尝试使用相同的按钮组件,但标签和链接不同。
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
ButtonView(text: "first", link: FirstView())
.padding()
ButtonView(text: "second", link: SecondView())
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
传递字符串参数有效。标签不同。但我不能让它与不同视图的链接一起使用。我收到一个错误:
Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements
保持第一个视图和第二个视图相同,对 ButtonView 使用以下内容:
struct ButtonView<Content : View>: View {
@State private var showModal: Bool = false
var text: String
// This is the generic content parameter
let content: Content
init(text: String, @ViewBuilder contentBuilder: () -> Content){
self.text = text
self.content = contentBuilder()
}
var body: some View {
VStack {
Spacer()
Button(action: {
self.showModal = true
}) {
Text(text)
.padding(20)
.foregroundColor(Color.white)
}.sheet(isPresented: self.$showModal) {
content
}
.background(Color.blue)
}
}
}
此处名为 content 的通用参数用于接收任何视图,初始化程序与 @ViewBuilder 属性 包装器一起使用以构建 view.Now 在 ContentView 结构中按以下方式使用它:
struct ContentView: View {
var body: some View {
HStack {
ButtonView(text: "First") {
FirstView()
}
ButtonView(text: "Second") {
SecondView()
}
}
}
}
它会很有魅力:)
此外,如果您想保留 ButtonView 的预览并且不希望它崩溃,请将预览添加为:
struct ButtonView_Previews: PreviewProvider {
static var previews: some View {
ButtonView(text: "First") {
FirstView()
}
}
}