我想使用List,@FocusState来跟踪焦点,并.onChanged(of: focus)确保当前聚焦的字段通过 可见ScrollViewReader。问题是:当所有内容都设置在一起时,List滚动过程中会不断重建,从而使滚动不那么平滑。
我发现当List我附加时会在滚动时重建.onChanged(of: focus)。List如果我替换为,问题就消失了ScrollView,但我喜欢 的外观List,我需要部分支持,并且我需要编辑功能(例如删除、移动项目),所以我需要坚持查看List。
我用它Self._printChanges()来看看是什么让主体在滚动时重建自身,输出如下:
ContentView: _focus changed.
ContentView: _focus changed.
ContentView: _focus changed.
ContentView: _focus changed.
...
Run Code Online (Sandbox Code Playgroud)
附在 上的封条上没有打印任何内容.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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
我建议考虑将列表行内容分离到独立视图中,并使用诸如焦点“选择”方法之类的方法。每行的内部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
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4830 次 |
| 最近记录: |