SwiftUI滚动容器ScrollViewReader
SwiftUI滚动容器ScrollViewReader

SwiftUI滚动容器ScrollViewReader

ScrollViewReader 是 SwiftUI 中一个非常有用的容器,它通过编程的方式控制 ScrollView 的滚动行为,例如滚动到指定的位置、实现动态滚动等。

ScrollViewReader 的结构

ScrollViewReader { proxy in
    ScrollView {
        内容视图
    }
}

参数说明

proxy:一个 ScrollViewProxy 对象,提供滚动控制的方法,例如:

scrollTo(_:anchor:):滚动到指定的视图。

proxy.scrollTo(25, anchor: .center) // 滚动到 ID 为 25 的行,居中显示

上述代码会滚动到ID为25的行。

注意

需要在视图中为目标内容设置唯一的 .id() 标识符,proxy.scrollTo() 会根据这个标识符找到目标内容并滚动过去。

ForEach(0..<100, id: \.self) { index in
    Text("Item \(index)")
        .id(index) // 为每行设置唯一的 ID
}

例如,在上述代码中给Text文本视图添加.id()标识符。

基本用法示例

1、滚动到特定行

以下代码展示了点击按钮时滚动到指定的行:

struct ContentView: View {
    var body: some View {
        ScrollViewReader { proxy in
            VStack {
                Button("Scroll to Item 25") {
                    withAnimation {
                        proxy.scrollTo(25, anchor: .center) // 滚动到 ID 为 25 的行,居中显示
                    }
                }
                .padding()
                
                ScrollView {
                    LazyVStack {
                        ForEach(0..<100, id: \.self) { index in
                            Text("Item \(index)")
                                .padding()
                                .frame(maxWidth: .infinity)
                                .background(Color.blue.opacity(0.2))
                                .cornerRadius(8)
                                .id(index) // 为每行设置唯一的 ID
                        }
                    }
                }
            }
        }
    }
}

在ScrollView中给每个Text视图绑定id后,在ScrollViewReader容器中,设置按钮为proxy.scrollTo(),点击按钮会自动跳转到响应行数。

2、在视图加载时滚动到特定位置

可以在视图加载完成时通过 .onAppear 方法让 ScrollView 自动滚动到某个特定位置:

struct ScrollToOnAppearExample: View {
    var body: some View {
        ScrollViewReader { proxy in
            ScrollView {
                LazyVStack {
                    ForEach(0..<100, id: \.self) { index in
                        Text("Item \(index)")
                            .padding()
                            .frame(maxWidth: .infinity)
                            .background(Color.green.opacity(0.2))
                            .cornerRadius(8)
                            .id(index) // 标记每行的 ID
                    }
                }
            }
            .onAppear {
                // 滚动到第 50 行,并将其放在顶部
                proxy.scrollTo(50, anchor: .top)
            }
        }
    }
}

在onAppear中设置proxy.scrollTo()后,视图打开时会自动跳转到设置的对应行数,例如示例代码中的第50行。

3、使用动态滚动和用户交互

可以结合用户输入(如滑块)来控制滚动行为:

struct DynamicScrollExample: View {
    @State private var targetIndex = 0

    var body: some View {
        ScrollViewReader { proxy in
            VStack {
                Slider(value: $targetIndex, in: 0...99, step: 1)
                    .padding()
                    .onChange(of: targetIndex) { newValue in
                        // 滚动到用户选择的位置
                        proxy.scrollTo(Int(newValue), anchor: .center)
                    }

                Text("Scrolling to Item \(Int(targetIndex))")
                    .font(.headline)
                    .padding()

                ScrollView {
                    LazyVStack {
                        ForEach(0..<100, id: \.self) { index in
                            Text("Item \(index)")
                                .padding()
                                .frame(maxWidth: .infinity)
                                .background(Color.orange.opacity(0.2))
                                .cornerRadius(8)
                                .id(index)
                        }
                    }
                }
            }
        }
    }
}

通过拖动Slider可以跳转到ScrollView中对应的Text位置。

scrollTo 方法参数

proxy.scrollTo(_:anchor:) 是核心方法,用于滚动到指定位置。

参数说明

1、id

标识要滚动到的视图的 ID,必须与 .id() 一致。

2、anchor

滚动视图中的目标位置,可以是以下值:

.top:目标视图的顶部对齐。

.center:目标视图居中对齐。

.bottom:目标视图的底部对齐。

自定义 UnitPoint 值(例如:UnitPoint(x: 0.5, y: 0.8))。

注意事项

1、.id() 必须唯一

滚动目标的视图需要明确设置唯一的 ID,否则无法正确定位。

2、嵌套滚动的行为

如果在嵌套 ScrollView 中使用 ScrollViewReader,可能会产生滚动冲突。需要确保 ScrollViewReader 作用域正确。

3、动画滚动

默认情况下,scrollTo 是瞬间滚动。为了添加动画,可以将其包装在 withAnimation 中:

withAnimation {
    proxy.scrollTo(targetID, anchor: .center)
}

常见用途

1、跳转到特定内容

点击按钮、滑块或其他触发器后,跳转到对应位置。

2、视图初始化时定位

自动滚动到特定视图,例如展示最近的活动或最下方的聊天消息。

3、滚动监听与动态调整

结合其他视图或手势控制滚动行为。

总结

ScrollViewReader 是 SwiftUI 中为 ScrollView 提供编程控制的强大工具,配合动态内容(如 LazyVStack)和用户交互,可以实现流畅的滚动体验。通过 .id() 和 scrollTo 方法,可以精确控制滚动视图中的定位和动画效果,极大提高用户体验的灵活性和便利性。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注