微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SwiftUI ScrollViewReader 在调整大小时保留滚动位置

如何解决SwiftUI ScrollViewReader 在调整大小时保留滚动位置

当使用 ScrollViewReader 滚动到某个位置时,例如到宽度的 40% - 当 ScrollView 的内容调整大小时,如何保留滚动位置?

我写了一个小示例应用程序来说明问题:

最初,ScrollView 的 child 的宽度为 1600,滚动位置在 40%。当您单击“将宽度更改为 800”按钮时,子宽度将更改为 800,并且 ScrollView 滚动到末尾。 我希望 ScrollView 在调整大小后保留滚动位置,或者在调整大小后始终滚动到 40%。

struct ContentView: View {

    @State private var relativeScrollPosition: Double?
    @State private var childWidth: CGFloat = 1600


    var body: some View {
        vstack {
            Button("Change width to 800") {
                childWidth = 800
            }
            Button("Change width to 1600") {
                childWidth = 1600
            }
            RelativeScrollView(
                relativeScrollPosition: $relativeScrollPosition,childWidth: childWidth
            ) {
                HStack{
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("1")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("2")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("3")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("4")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("5")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("6")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("7")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("8")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("9")
                    }
                    ZStack {
                        Spacer().frame(height: 100).background(Color.green)
                        Text("10")
                    }
                }
                .frame(width: childWidth,height: 100,alignment: .center)
            }
            .onAppear {
                scrollTo40percent()
            }
            .onChange(of: childWidth,perform: { _ in
                scrollTo40percent()
            })
        }
    }

    private func scrollTo40percent() {
        relativeScrollPosition = 0.4
    }
}


struct RelativeScrollView<Content: View>: View {

    @Binding var relativeScrollPosition: Double?
    let childWidth: CGFloat
    let isAnimating = true
    var child: () -> Content

    var body: some View {
        ScrollViewReader { reader in
            ScrollView(.horizontal) {
                ZStack {
                    HStack {
                        // swiftlint:disable identifier_name
                        ForEach(0..<101) { i in
                            Spacer().id(i)
                        }
                    }
                    .frame(width: childWidth)
                    self.child()
                }
            }
            .onAppear {
                scroll(reader,to: relativeScrollPosition)
            }
            .onChange(of: relativeScrollPosition) { newPos in
                scroll(reader,to: newPos)
            }
        }
    }

    private func scroll(_ reader: ScrollViewProxy,to position: Double?) {
        guard let unwrappedPosition = position else { return }
        assert(unwrappedPosition >= 0 && unwrappedPosition <= 1)
        let elementToScrollTo = Int(unwrappedPosition * 100)
        if isAnimating {
            withAnimation {
                reader.scrollTo(elementToScrollTo,anchor: .center)
            }
        } else {
            reader.scrollTo(elementToScrollTo,anchor: .center)
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?