SwiftUI控件之 ScrollView(二)
实现快速滚动到顶部或底部的效果
在很多的ScrollView 的应用中,我们经常见到点击“回到顶部”按钮实现快速回到顶部的效果。
在 SwiftUI中,如果我们想要实现这样的效果,我们可以使用ScrollViewRader和ScrollView来实现。ScrollViewRader可以让我们通过编程的方式实现滚动到一个已知的子视图的位置。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
struct ContentView: View {
var topID
var bottomID
var body: some View {
ScrollViewReader { proxy in
ScrollView {
// 顶部的按钮
Button {
withAnimation {
proxy.scrollTo(bottomID)
}
} label: {
Text("滚动到底部")
}
.id(topID)
// 滚动视图
VStack(spacing: 0.1) {
ForEach(0..<100) {i in
color(fraction: Double(i) / 100)
.frame(height: 32)
}
}
// 顶部的按钮
Button(action: {
withAnimation {
proxy.scrollTo(topID)
}
}, label: {
Text("滚动到顶部")
})
.id(bottomID)
}
}
}
// 创建颜色
func color(fraction: Double) -> Color {
Color(red: fraction, green: 1 - fraction, blue: 0.5)
}
}
在上面的示例代码中,实现了一下几个步骤:
- 在
ScrollView外面嵌套了一层ScrollViewReader; ScrollView的子视图包括顶部按钮、 100 个渐变颜色子视图和底部按钮是三个部分;- 使用
@NameSpace创建了topID和bottomID两个变量,然后将它们分别给到顶部和底部按钮; - 利用
ScrollViewRader提供的proxy在点击两个按钮的时候滚动到指定的 ID 的子视图位置。
效果如下:
实现滚动到指定索引的位置
创建一个数据结构:1
2
3
4
5struct NameModel: Identifiable {
let name:String
let id: String = UUID().uuidString
let index: Int
}
生成一些测试使用的数据源:1
2
3
4
5
6
7
8// 数据源
var nameDatas:[NameModel] {
get {
(0..<100).map {
NameModel(name: "我是-\($0)", index: $0)
}
}
}
界面布局:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19var body: some View {
ScrollViewReader { proxy in
ScrollView {
Button(action: {
withAnimation {
proxy.scrollTo(nameDatas[scrollToIndex].index)
}
}, label: {
Text("滚动到索引为\(scrollToIndex)的地方")
})
ForEach(nameDatas) { data in
Text(data.name)
.padding(4)
.id(data.index)
}
}
}
}
此时的效果为当我们点击按钮后,ScrollView将滚动到子视图 ID为 70 的位置:
注意:这里目前依然存在一个问题,当我们使用数据模型的id属性作为ScrollView子视图的ID 时,即 .id(data.id),无法实现类似的效果。