SwiftUI 布局: ScrollView 使用 Geomet
当我们使用GeometryReader
的frame(in:)
方法时,SwiftUI将计算视图在所需坐标空间中的当前位置。但是,随着视图移动,这些值将更改,SwiftUI将自动确保GeometryReader
保持更新。
以前我们使用DragGesture
将宽度和高度存储为@State
属性,因为它允许我们根据拖动量调整其他属性以创建整洁的效果。但是,借助GeometryReader
,我们可以动态地从视图环境中获取值,将其绝对或相对位置输入各种修改器中。更好的是,您可以嵌套读取,以便一个可以获取更上层的视图,而另一个可以获取位于该视图下方的内容。
为了说明这一点,我们可以通过在垂直滚动视图中创建50个文本视图来创建旋转螺旋效果,每个文本视图都使用最顶部视图的整个宽度,然后根据其自身位置应用3D旋转效果。
首先制作一个具有不同背景颜色的基本ScrollView
文本视图:
struct ContentView: View {
let colors: [Color] = [.red, .green, .blue, .orange, .pink, .purple, .yellow]
var body: some View {
GeometryReader { fullView in
ScrollView(.vertical) {
ForEach(0..<50) { index in
GeometryReader { geo in
Text("Row #\(index)")
.font(.title)
.frame(width: fullView.size.width)
.background(self.colors[index % 7])
}
.frame(height: 40)
}
}
}
}
}
要应用螺旋样式的旋转效果,请将以下rotation3DEffect()
直接放在background()
修饰符下方:
.rotation3DEffect(.degrees(Double(geo.frame(in: .global).minY) / 5), axis: (x: 0, y: 1, z: 0))
当您向下滑动时,您会看到屏幕底部的文本视图被翻转,中心的文本视图旋转了90度,最顶部的文本视图是正常的。更重要的是,当您滚动时,它们都随着滚动视图的移动而旋转。
这是一个很好的效果,但是也有问题,因为视图只有在最顶部时才达到自然方向——很难阅读。为了解决这个问题,我们可以应用更复杂的rotation3DEffect()
它减去了主视图高度的一半:
.rotation3DEffect(.degrees(Double(geo.frame(in: .global).minY - fullView.size.height / 2) / 5), axis: (x: 0, y: 1, z: 0))
rotation3DEffect_y/2
将其放置在适当的位置后,视图将在靠近屏幕中心的地方达到自然的方向,看起来会更好。
我们可以使用类似的技术来创建CoverFlow
样式的滚动矩形,这次添加一些填充,以便视图自然地位于开始和结束的中心:
struct ContentView: View {
let colors: [Color] = [.red, .green, .blue, .orange, .pink, .purple, .yellow]
var body: some View {
GeometryReader { fullView in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<50) { index in
GeometryReader { geo in
Rectangle()
.fill(self.colors[index % 7])
.frame(height: 150)
.rotation3DEffect(.degrees(-Double(geo.frame(in: .global).midX - fullView.size.width / 2) / 10), axis: (x: 0, y: 1, z: 0))
}
.frame(width: 150)
}
}
.padding(.horizontal, (fullView.size.width - 150) / 2)
}
}
.edgesIgnoringSafeArea(.all)
}
}
rotation3DEffect_x/2
使用GeometryReader
制作特殊效果的方法有很多有趣且富创意的方法——我希望您可以花些时间进行实验!