我有
TextField
以应当在特定用户动作上动态更新的形式。既然我嵌入了这个
SwiftUI
内部视图
UIKit
视图,我不得不对其进行一些自定义:
/// Base TextField
struct CustomTextFieldSUI: View {
@State var text: String = ""
var placeholder: Text
var disableAutoCorrect = false
var isSecure: Bool = false
var onEditingChanged: (Bool) -> () = { _ in }
var onCommit: () -> () = { }
var onChange: (String) -> Void
var keyboardType: UIKeyboardType = .default
var contentType: UITextContentType?
var body: some View {
ZStack(alignment: .leading) {
if text.isEmpty {
placeholder
.foregroundColor(placeholderColor)
}
if isSecure {
SecureField("", text: $text.onChange({ newText in
onChange(newText)
}), onCommit: onCommit)
.foregroundColor(foregroundColor)
} else {
TextField("", text: $text.onChange({ newText in
onChange(newText)
}), onEditingChanged: onEditingChanged, onCommit: onCommit)
.foregroundColor(foregroundColor)
.disableAutocorrection(disableAutoCorrect)
.keyboardType(keyboardType)
.textContentType(contentType)
.autocapitalization(keyboardType == UIKeyboardType.emailAddress ? .none : .words)
}
}
}
}
其本身用于创建另一个自定义视图:
struct TextFieldWithIconSUI: View {
@State var text: String = ""
@State var isSecure: Bool
let icon: Image
let placeholder: String
var prompt: String? = nil
let disableAutoCorrect: Bool = false
var keyboardType: UIKeyboardType = .default
var contentType: UITextContentType?
var onEditingChanged: (Bool) -> () = { _ in }
var onCommit: () -> () = { }
var onChange: (String) -> Void
var body: some View {
VStack {
ZStack {
RoundedRectangle(cornerRadius: 0)
HStack(alignment: .center, spacing: iconSpacing) {
CustomTextFieldSUI(
text: text,
placeholder: Text(placeholder),
placeholderColor: .gray,
foregroundColor: .white,
disableAutoCorrect: disableAutoCorrect,
isSecure: isSecure, onEditingChanged: onEditingChanged, onCommit: onCommit, onChange: { newText in
text = newText
onChange(newText)
},
keyboardType: keyboardType,
contentType: contentType)
icon
.scaledToFit()
.onTapGesture {
isSecure.toggle()
}
}
}
if (prompt != nil) {
VStack(alignment: .leading) {
Text(prompt!)
.padding(.leading, 10)
.padding(.top, -2)
.frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(2)
}
}
}
}
}
现在,在客户端视图中,我将它与列表一起使用,以创建一个简单的自动完成列表:
TextFieldWithIconSUI(text: displayCountryName, isSecure: false, icon: emptyImage, placeholder: "Country", keyboardType: .default, contentType: .countryName, onEditingChanged: { changed in
self.shouldShowCountriesList = changed
}, onChange: { text in
self.displayCountryName = text
self.shouldShowCountriesList = true
})
在我表单的某个地方,我使用TextField中的文本来显示自动更正列表。会显示列表,但当我选择一个项时,它不会更新TextField的文本,在调试器中,状态变量会更新,但UI不会显示新值。
if shouldShowCountriesList {
VStack(alignment: .leading) {
List {
ForEach(countriesList.filter { $0.lowercased().hasPrefix(country.object.lowercased()) }.prefix(3), id: \.self) { countryName in
Text(countryName)
.onTapGesture {
self.displayCountryName = countryName
self.shouldShowCountriesList = false
}
}
}
}
}