簡體   English   中英

在 SwiftUI 中獲取 List 的內容偏移量

[英]Getting content offset of List in SwiftUI

我正在嘗試在 SwiftUI 中創建這樣的視差標題效果https://twitter.com/KhaosT/status/1140814602017464320 ,但真的不知道如何在滾動時獲取列表的內容偏移量。

有誰知道如何在滾動時計算列表的內容偏移量?

我在這個答案中ScrollView案例提供了一個可重用的解決方案,它利用視圖首選項作為一種方法來通知視圖層次結構中的上游布局信息。

有關“查看首選項”如何工作的詳細說明,我建議您閱讀kontiki 撰寫的關於該主題的3 篇系列文章

不幸的是,這種解決方案不適用於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
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM