我正在努力为SwiftUI编写自己的BetterTextField
视图,因为内置的TextField
在几个方面都缺乏。即,我想支持延迟绑定(仅在定位焦点时更新绑定值,而不是在每次按键后强制重画),程序化聚焦/响应器控制以及SwiftUI缺少的UIKit UITextField
的其他一些功能。 / p>
因此,我创建了一个自定义UIViewRepresentable
,其中的协调者为UITextFieldDelegate
,这很好用。但是,为了与其他视图保持一致,我真的很想让我的自定义文本字段适应某些现有的SwiftUI修饰符。
例如:
// Here's my content view
struct ContentView: View {
var body: some View {
BetterTextField("Username", text: $username)
// I want to adapt the view to this modifier
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}
// Here's my (simplified) custom text field view
struct BetterTextField: UIViewRepresentable {
var title: String
@Binding var text: String
init(_ title: String, text: Binding<String>) {
self.title = title
self._text = text
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField()
textField.placeholder = title
return textField
}
func updateUIView(_ view: UITextField, context: Context) {
view.text = text
// How can I check for the .textFieldStyle() modifier here and set the corresponding UIKit style accordingly?
view.borderStyle = .roundedRect
}
}
正如评论所说,如何调整borderStyle
的{{1}}属性以匹配“视图”修饰符?
更笼统地说,如何检查修饰符的存在并返回适当样式的自定义视图(例如UITextField
转换为属性文本)?
答案 0 :(得分:1)
View
修饰符只是再次返回some View
的函数,因此您可以实现对任何修饰符的支持,并符合您决定适合自定义类型的任何协议。您的控件在每个已实现的修饰符上的行为方式取决于您。
以下是对textFieldStyle
修饰符的简单演示支持,使您的ContentView
渲染BetterTextField
的目的取决于添加的圆角矩形样式修饰符或已删除。
struct BetterTextField: UIViewRepresentable {
var title: String
@Binding var text: String
private let textField = UITextField()
init(_ title: String, text: Binding<String>) {
self.title = title
self._text = text
}
func makeUIView(context: Context) -> UITextField {
textField.placeholder = title
return textField
}
func updateUIView(_ view: UITextField, context: Context) {
view.text = text
}
}
extension BetterTextField {
func textFieldStyle<S>(_ style: S) -> some View where S : TextFieldStyle {
if style is RoundedBorderTextFieldStyle {
self.textField.borderStyle = .roundedRect
}
return self
}
}
答案 1 :(得分:0)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {
/// Sets the style for `TextField` within the environment of `self`.
public func textFieldStyle<S>(_ style: S) -> some View where S : TextFieldStyle
}
查看注释
在TextField
环境中设置self
的样式
UIViewRepresentable继承自View,但“自身”中没有任何TextField
.bold,.italic ...是Font的修饰符,而不是通用View的修饰符。说
Image("image001").italic()
效果不好。
有关反跳的信息,请参见Debounced Property Wrapper
有关“延迟”绑定,请参见
/// Creates an instance with a `Text` label generated from a localized title
/// string.
///
/// - Parameters:
/// - titleKey: The key for the localized title of `self`, describing
/// its purpose.
/// - text: The text to be displayed and edited.
/// - onEditingChanged: An `Action` that will be called when the user
/// begins editing `text` and after the user finishes editing `text`,
/// passing a `Bool` indicating whether `self` is currently being edited
/// or not.
/// - onCommit: The action to perform when the user performs an action
/// (usually the return key) while the `TextField` has focus.
public init(_ titleKey: LocalizedStringKey, text: Binding<String>, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {})
“延迟”绑定的示例
import SwiftUI
struct MyTextField<S>: View where S: StringProtocol {
let label: S
@State private var __text = ""
@Binding var text: String
var body: some View {
TextField(label, text: $__text, onEditingChanged: { (e) in
}) {
self.text = self.__text
}
}
}
struct ContentView: View {
@State var text = " "
var body: some View {
VStack {
MyTextField(label: "label", text: $text).textFieldStyle(RoundedBorderTextFieldStyle())
Text(text)
}.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
如果您需要不同的字体和.bold,请使用
MyTextField(label: "label", text: $text).textFieldStyle(RoundedBorderTextFieldStyle()).font(Font.title.bold())
或
MyTextField(label: "label", text: $text).font(Font.title.bold()).textFieldStyle(RoundedBorderTextFieldStyle())