我正在创建一个自定义TextField视图,该视图由多个装饰视图组成。我希望能够设置内部TextField的视图修饰符,如键盘,大写等,只适用于该子视图。
与其为每个属性创建属性,我认为最好的方法是传入一个可选的ViewModifier参数并使用它,如下所示:
struct MySuperTextField: View {
var vm: ViewModifier?
var body: some View {
TextField(...)
.modifier( vm ?? EmptyModifier() )
// ... more views here
}
}由于associatedType in ViewModifier,这是不起作用的。唉,也没有像AnyViewModifier这样的东西(我也想不出如何使它起作用)。
有人能做这样的事吗?我在网上找不到任何东西。
一个例子就是
struct LastNameModifier: ViewModifier {
func body(content: Content) -> some View {
content
.autocapitalization(.words)
.textContentType(.familyName)
.backgroundColor(.green)
// ... anything else specific to names
}
}
struct EmailModifier: ViewModifier {
func body(content: Content) -> some View {
content
.keyboardType(.emailAddress)
.textContentType(.emailAddress)
.backgroundColor(.yellow)
// ... anything else specific to emails
}
}然后像这样在我的MySuperTextField中使用它们:
VStack {
MySuperTextField("Last Name", $lastName, vm: LastNameModifier())
MySuperTextField("Email", $email, vm: EmailModifier())
}发布于 2021-01-17 18:01:37
如果我正确理解,您可以让MySuperTextField接受一个通用参数:
struct MySuperTextField<V>: View where V: ViewModifier {
private let placeholder: String
@Binding private var text: String
private let vm: V
init(_ placeholder: String, text: Binding<String>, vm: V) {
self.placeholder = placeholder
self._text = text
self.vm = vm
}
var body: some View {
TextField(placeholder, text: $text)
.modifier(vm)
}
}然后,可以传递一些ViewModifier作为参数:
struct ContentView: View {
@State private var text: String = "Test"
var body: some View {
MySuperTextField("Last Name", text: $text, vm: LastNameModifier())
}
}如果您需要在创建vm时跳过MySuperTextField参数
MySuperTextField("Last Name", text: $text)您可以创建一个扩展:
extension MySuperTextField where V == EmptyModifier {
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
self.vm = EmptyModifier()
}
}发布于 2021-01-17 18:04:37
由于ViewModifier有一个关联类型,您不能将其用作实例变量,但我建议您使用另一种方法:
MySuperTextField不必维护ViewModifier类型的实例。
struct MySuperTextField: View {
@State var textValue = ""
var body: some View {
TextField("", text: $textValue)
}
}对于每个符合ViewModifier协议的结构,您可以创建一个扩展:
extension MySuperTextField {
func lastNameModifier() -> some View {
modifier(LastNameModifier())
}
func emailModifier() -> some View {
modifier(EmailModifier())
}
}你可以这样用它:
struct ContentView : View {
var body: some View {
VStack {
MySuperTextField(textValue: "Last Name")
.lastNameModifier()
MySuperTextField(textValue: "Email")
.emailModifier()
}
}
}发布于 2021-01-16 18:30:14
将ViewModifier设置为一个结构,然后在视图上调用它。您只需特定于类型,例如我使用的这个buttonStyle修饰符:
struct PurchaseButtonStyle: ButtonStyle {
let geometry: GeometryProxy
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(minWidth: 0, idealWidth: 300, maxWidth: .infinity)
.padding(.all, geometry.size.height / 30)
.foregroundColor(.black)
.background(.orange)
.cornerRadius(30)
}
}其用途是:
Button(...)
.buttonStyle(PurchaseButtonStyle(geometry: Geometry))您只需编写它就可以成为特定的修饰符。我之所以使用这个,是因为它在我正在开发的一个应用程序中非常方便。
https://stackoverflow.com/questions/65752883
复制相似问题