我需要有许多文本字段来处理表单之类的内容。总是有类似键文本字段和值文本字段之类的东西。所以我想使用具有两列的 LazyVGrid。 此时每个文本字段都使用自定义绑定,这就是文本字段:
struct FocusField: View {
@State var index: Int
@Binding var focus: String?
@Binding var content: [String]
@FocusState var isFocused: String?
var nextFocus: () -> Void
@ObservedObject var player = Player.shared
var body: some View {
if index < content.endIndex {
HStack{
TextField(((index % 2 == 0) ? player.language1 : player.language2),
text:
Binding<String>(
get: {
if content.endIndex > index {
return content[index]
}
return ""
}, set: {newValue in
if content.endIndex > index {
content[index] = newValue
}
}
)
// ,
// axis: .vertical
)
#if os(iOS)
.autocapitalization(UITextAutocapitalizationType.none)
#endif
.multilineTextAlignment(.leading)
.onSubmit {
self.nextFocus()
}
.onChange(of: focus, perform: { newValue in
self.isFocused = newValue
})
.focused(self.$isFocused, equals: "\(content[index])\(index)")
if isFocused == "\(content[index])\(index)"{
if index % 2 != 0{
Button(role: .destructive) {
if content.count > 2 {
content.remove(at: index)
content.remove(at: index)
} else {
content = ["",""]
}
} label: {
Image(systemName: "trash.fill")
}
}
}
}
}
}
}
这是我如何使用它们。在具有两列的 LazyVGrid 内部:
struct EditViewInDetailView: View{
@Binding var item: Item?
@ObservedObject var viewModel = VocabDetailViewModel.shared
@State var focus: String? = nil
@Binding var isExpanded : PresentationDetent
let columns : [GridItem] = Array(repeating: .init(.flexible()), count: 2)
var body: some View{
ScrollViewReader{scroll in
ScrollView{
LazyVGrid(columns: columns) {
ForEach(0..<(viewModel.content.count), id: \.self) { index in
LazyVStack{
Spacer()
FocusField(index: index, focus: $focus, content: $viewModel.content) {
if index % 2 != 0 {
viewModel.content.insert("", at: (index % 2 == 0 ? (index+2) : (index + 1)) )
viewModel.content.insert("", at: (index % 2 == 0 ? (index+2) : (index + 1)) )
}
DispatchQueue.main.asyncAfter(deadline: .now() + (0.01 * Double(index)) ) {
focus = "\(viewModel.content[index+1])\(index+1)"
}
}
Spacer()
Divider()
.padding(.horizontal, -10)
.background(.gray)
}
}
}
Button("Zurück"){
isExpanded = .height(81)
}
.buttonStyle(BorderedProminentButtonStyle())
Spacer()
.frame(height: 100)
}
}
}
}
如果有很多文本字段,滚动性能会大幅下降,并且无法在索引较高的字段中输入内容。当您点击文本字段时,键盘会立即显示并退出。
我尝试使用文本代替,并在聚焦时将文本更改为文本字段,但它没有更改为文本字段。
有人知道代码的哪一部分使它如此慢吗?
我认为你应该使用一个迭代键值对的列表。那么您不需要检查索引 % 2 并且不需要自定义绑定。对于删除,您可以使用 .onDelete 修饰符而不是自定义删除按钮。由于代码更简单,您可以直接在包含列表的视图中使用 focusstate。所以你不需要 isFocused 属性。而且它看起来应该好多了;-).