【问题标题】:Getting content offset of List in SwiftUI在 SwiftUI 中获取 List 的内容偏移量
【发布时间】:2019-11-05 15:48:10
【问题描述】:

我正在尝试在 SwiftUI 中创建像 https://twitter.com/KhaosT/status/1140814602017464320 这样的视差标题效果,但我真的不知道如何在滚动时获取列表的内容偏移量。

有谁知道如何在滚动时计算列表的内容偏移量?

【问题讨论】:

  • 在对该推文的回复中,作者建议使用GeometryReader 来获取它。你测试过这种方法吗?
  • 是的,我设法使用GeometryReaderScrollView 获取内容偏移量,仍在研究如何将相同的技术应用于ListScrollView 的源代码在这里:github.com/peacemoon/SwiftUIParallaxHeader/blob/master/…
  • 仍在寻找 List 的解决方案。任何人都发现了任何东西(我正在使用 Beta3,但据我所知仍然没有爱)。
  • 这可能会有所帮助。 stackoverflow.com/questions/56729619/…
  • @Peacemoon 我请您回答原始问题。你不应该回答并接受是正确的吗?还是需要完整的解决方案?

标签: ios list offset swiftui


【解决方案1】:

我为 answer 上的 ScrollView 案例提供了一个可重用的解决方案,它使用 View Preferences 作为在 View Hierarchy 中通知上游布局信息的方法。

关于View Preferences如何工作的详细解释,我建议阅读3 articles serieskontiki的主题

不幸的是,这种解决方案不适用于 List(可能是一个错误),因为 View Preferences 被困在 List 中并且其祖先不可见。

目前唯一可行的解​​决方案是观察列表内视图的框架变化。您可以通过两种方式实现这一目标:

您可以报告和收听列表中每个视图(单元格)的布局更改(并对其采取行动):

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
    }
}

【讨论】:

  • 文本 ("") 左上方偏移
  • 我如何知道列表是在顶部还是被滚动?得到一个布尔答案。
猜你喜欢
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
相关资源
最近更新 更多