我想扩展 SwiftUI.Button 以便我可以添加一个类型道具并将该类型更改为不同类型的主题按钮。但我是 Swift 的新手,我不知道如何让我的标签和动作道具通用。
换句话说,如果我这样做
/api/image
它限制闭包只允许标签返回 text()
如何做到这一点
还有关于我应该如何根据类型更改对按钮所做的“更改”的任何建议。
注意: 有人对此表示反对,因为它类似于来自另一个用户的 button style 查询,但事实并非如此。
该解决方案只是将预制样式添加到默认的 SwiftUI.button 结构中,这不是我的目标。
我正在尝试使用可以传递的类型属性扩展 SwiftUI.Button,并将根据该输入设置样式。
虽然他们分享相同的结果,但他们并没有完成相同的目标。我的解决方案将提供可在整个项目中使用的动态样式组件。无需尾随 import SwiftUI
struct Button: View {
var type: String = ""
var action = {}
var label = {
Text("Button")
}
var body: some View {
ZStack(content: {
SwiftUI.Button(action: action, label: label)
})
}
}
答案 0 :(得分:0)
正如我所看到的,您正在尝试重新创建苹果按钮,您可以这样做,然后在正文中进行自定义:
struct Button<Content: View>: View {
let action: () -> Void
let label: () -> Content
init(action: @escaping () -> Void, @ViewBuilder label: @escaping () -> Content) {
self.action = action
self.label = label
}
init(action: @escaping () -> Void, title: String) where Content == Text {
self.init(action: action, label: { Text(title) })
}
var body: some View { label().onTapGesture { action() } }
}
用例:
Button(action: { print("hello") }, label: { Text("Button") })
Button(action: { print("hello") }, title: "Button")
答案 1 :(得分:0)
swiftPunk 的结论如下。
struct Button<Content: View>: View {
let type: button_styles
let action: () -> Void
let label: () -> Content
enum button_styles {
case filled
case outlined
case plain
}
init(type: button_styles, action: @escaping () -> Void, @ViewBuilder label: @escaping () -> Content ) {
self.type = type
self.action = action
self.label = label
}
init(type: button_styles, action: @escaping () -> Void, title: String) where Content == Text {
self.init(type: type, action: action, label: { Text(title) })
}
init(action: @escaping () -> Void, title: String) where Content == Text {
self.init(type: .plain, action: action, label: { Text(title) })
}
init(action: @escaping () -> Void, @ViewBuilder label: @escaping () -> Content) {
self.init(type: .plain, action: action, label: label)
}
var body: some View {
switch type {
case .filled:
SwiftUI.Button(action: self.action, label: self.label).buttonStyle(FilledButtonStyle())
case .outlined:
SwiftUI.Button(action: self.action, label: self.label).buttonStyle(OutlinedButtonStyle())
case .plain:
SwiftUI.Button(action: self.action, label: self.label).buttonStyle(PlainButtonStyle())
}
}
}
struct FilledButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.font(.headline)
.frame(maxWidth: 108, maxHeight: 34, alignment: .center)
.contentShape(Rectangle())
.foregroundColor(configuration.isPressed ? Color.white.opacity(0.5) : Color.white)
.background(configuration.isPressed ? Color("Red").opacity(0.5) : Color("Red"))
.cornerRadius(20)
}
}
struct OutlinedButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.font(.headline)
.frame(maxWidth: 108, maxHeight: 34, alignment: .center)
.foregroundColor(Color("Grey"))
.background(Color.white.opacity(0))
.overlay(RoundedRectangle(cornerRadius:10).stroke(Color("Grey"), lineWidth: 2))
}
}
struct PlainButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.font(.headline)
.frame(maxWidth: 108, maxHeight: 34, alignment: .center)
.contentShape(Rectangle())
.foregroundColor(configuration.isPressed ? Color.white.opacity(0.5) : Color("Grey"))
}
}
这将允许您使用按钮结构,例如:
Button(type: .outlined, action: { print("pressed") }, title: "Button")
或
Button(action: { print("pressed") }, title: "Button")
或
Button(action: addItem, label: {
Label("Add Item", systemImage: "plus")
})