我想用一个List
, @FocusState
跟踪焦点,以及.onChanged(of: focus)
确保当前聚焦的字段可见ScrollViewReader
。问题是:当一切都设置在一起时List
在滚动过程中不断重建,使得滚动不那么平滑。
我发现List
当我附加时滚动重建.onChanged(of: focus)
。如果我更换,问题就消失了List
with ScrollView
,但我喜欢的外观List
,我需要部分支持,并且我需要编辑功能(例如删除、移动项目),所以我需要坚持List
view.
I used Self._printChanges()
为了看看是什么让主体在滚动时重建自身,输出如下:
ContentView: _focus changed.
ContentView: _focus changed.
ContentView: _focus changed.
ContentView: _focus changed.
...
附在上面的封条上没有打印任何内容.onChanged(of: focus)
。下面是简化的示例,在此示例中滚动的平滑度不是问题,但是,一旦列表内容或多或少复杂,平滑滚动就会消失,这实际上是由于.onChanged(of: focus)
:(
问题:是否有机会监听焦点变化而不引起列表在滚动时重建自身?
struct ContentView: View {
enum Field: Hashable {
case fieldId(Int)
}
@FocusState var focus: Field?
@State var text: String = ""
var body: some View {
List {
let _ = Self._printChanges()
ForEach(0..<100) {
TextField("Enter the text for \($0)", text: $text)
.id(Field.fieldId($0))
.focused($focus, equals: .fieldId($0))
}
}
.onChange(of: focus) { _ in
print("Not printed unless focused manually")
}
}
}
我建议考虑将列表行内容分离到独立视图中,并使用诸如焦点“选择”方法之类的方法。拥有FocusState
每行的内部可防止父视图进行不必要的更新(我认为类似于预“设置”)。
使用 Xcode 13.4 / iOS 15.5 进行测试
struct ContentView: View {
enum Field: Hashable {
case fieldId(Int)
}
@State private var inFocus: Field?
var body: some View {
List {
let _ = Self._printChanges()
ForEach(0..<100, id: \.self) {
ExtractedView(i: $0, inFocus: $inFocus)
}
}
.onChange(of: inFocus) { _ in
print("Not printed unless focused manually")
}
}
struct ExtractedView: View {
let i: Int
@Binding var inFocus: Field?
@State private var text: String = ""
@FocusState private var focus: Bool // << internal !!
var body: some View {
TextField("Enter the text for \(i)", text: $text)
.focused($focus)
.id(Field.fieldId(i))
.onChange(of: focus) { _ in
inFocus = .fieldId(i) // << report selection outside
}
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)