【问题标题】:SwiftUI: How do I sync/change progress bar progress based on scrollview’s user current scroll position?SwiftUI:如何根据滚动视图的用户当前滚动位置同步/更改进度条进度?
【发布时间】:2021-02-18 22:19:56
【问题描述】:

我在 ScrollView 中有水平进度条,我需要在用户滚动时更改该进度条值。

有没有办法将一些值绑定到当前滚动位置?

【问题讨论】:

标签: swiftui scrollview


【解决方案1】:

您可以通过几个GeometryReaders 来做到这一点。

我的方法:

  1. 获取ScrollView容器的总高度
  2. 获取内容的内部高度
  3. 找出总可滚动高度的差异
  4. 获取滚动视图容器顶部和内容顶部之间的距离
  5. 将顶部之间的距离除以可滚动的总高度
  6. 使用PreferenceKeys 设置proportion @State

代码:

struct ContentView: View {
    @State private var scrollViewHeight: CGFloat = 0
    @State private var proportion: CGFloat = 0

    var body: some View {
        VStack {
            ScrollView {
                VStack {
                    ForEach(0 ..< 100) { index in
                        Text("Item: \(index + 1)")
                    }
                }
                .frame(maxWidth: .infinity)
                .background(
                    GeometryReader { geo in
                        let scrollLength = geo.size.height - scrollViewHeight
                        let rawProportion = -geo.frame(in: .named("scroll")).minY / scrollLength
                        let proportion = min(max(rawProportion, 0), 1)

                        Color.clear
                            .preference(
                                key: ScrollProportion.self,
                                value: proportion
                            )
                            .onPreferenceChange(ScrollProportion.self) { proportion in
                                self.proportion = proportion
                            }
                    }
                )
            }
            .background(
                GeometryReader { geo in
                    Color.clear.onAppear {
                        scrollViewHeight = geo.size.height
                    }
                }
            )
            .coordinateSpace(name: "scroll")

            ProgressView(value: proportion, total: 1)
                .padding(.horizontal)
        }
    }
}
struct ScrollProportion: PreferenceKey {
    static let defaultValue: CGFloat = 0

    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多