我正在尝试像这样的this one在SwiftUI中创建视差标题效果,但是我真的不知道如何在滚动时获取列表的内容偏移量。
有人知道滚动时如何计算列表的内容偏移量吗?
答案 0 :(得分:0)
我为此answer上的ScrollView
案例提供了可重用的解决方案,该解决方案利用了 View Preferences 作为在View层次结构中向上游通知布局信息的方法。 / p>
有关查看首选项的工作原理的详细说明,我建议您3 articles series
阅读本主题的kontiki不幸的是,这种解决方案不适用于List
(可能是一个错误),因为查看首选项被困在List
内并且其祖先不可见。 / p>
到目前为止,唯一可行的解决方案是观察列表内部视图上的框架变化。您可以通过两种方式实现这一目标:
您可以报告并聆听列表上每个视图(单元格)上的布局更改(并对其执行操作):
struct TestView1: View {
var body: some View {
GeometryReader { geometry in
List(TestEnum.allCases) { listValue in
Text(listValue.id)
.padding(60)
.transformAnchorPreference(key: MyKey.self, value: .bounds) {
$0.append(MyFrame(id: listValue.id, frame: geometry[$1]))
}
.onPreferenceChange(MyKey.self) {
print($0)
// Handle content frame changes here
}
}
}
}
}
或者,如果不需要每个单元格上的框架更改,则报告并监听某些表头视图(或空标题)上的框架更改:
struct TestView2: View {
var body: some View {
GeometryReader { geometry in
List {
Text("")
.transformAnchorPreference(key: MyKey.self, value: .bounds) {
$0.append(MyFrame(id: "tableTopCell", frame: geometry[$1]))
}
.onPreferenceChange(MyKey.self) {
print($0)
// Handle top view frame changes here.
// This only gets reported as long as this
// top view is part of the content. This could be
// removed when not visible by the List internals.
}
ForEach(TestEnum.allCases) {
Text($0.rawValue)
.padding(60)
}
}
}
}
}
找到以下解决方案的支持代码:PreferenceKey
一致性结构,可识别的视图框架结构和测试枚举作为数据源:
struct MyFrame : Equatable {
let id : String
let frame : CGRect
static func == (lhs: MyFrame, rhs: MyFrame) -> Bool {
lhs.id == rhs.id && lhs.frame == rhs.frame
}
}
struct MyKey : PreferenceKey {
typealias Value = [MyFrame] // The list of view frame changes in a View tree.
static var defaultValue: [MyFrame] = []
/// When traversing the view tree, Swift UI will use this function to collect all view frame changes.
static func reduce(value: inout [MyFrame], nextValue: () -> [MyFrame]) {
value.append(contentsOf: nextValue())
}
}
enum TestEnum : String, CaseIterable, Identifiable {
case one, two, three, four, five, six, seven, eight, nine, ten
var id: String {
rawValue
}
}