[英]Animate header when scroll in swiftui
I'm trying to build a view where the header is fixed at the top of the view and it changes it's size according to the scroll offset, when the offset is 0 the header is bigger and when the user scrolls the header becomes smaller我正在尝试构建一个视图,其中 header 固定在视图的顶部,它根据滚动偏移量改变它的大小,当偏移量为 0 时 header 更大,当用户滚动 Z099FB995346F346F319E44 时
struct ContentView : View {
@State var largeHeader = true
var body: some View {
VStack {
Text("HEADER").padding(.vertical, largeHeader ? 30 : 10)
Divider()
ScrollView {
VStack {
Text("Content0")
.padding()
Text("Content1")
.padding()
Text("Content2")
.padding()
}
.background(GeometryReader { geometryProxy -> Color in
DispatchQueue.main.async {
largeHeader = geometryProxy.frame(in: .named("myspace")).minY >= 0
}
return Color.clear
})
}
.coordinateSpace(name: "myspace")
}.animation(.default)
}
}
It works fine when the scroll content is longer, but when there is a little content, as in the code above I get this flickering (It's even worse on the device, but the gif quality is low)当滚动内容较长时它工作正常,但是当有一点内容时,如上面的代码中我得到这个闪烁(在设备上更糟,但 gif 质量低)
Any idea how to fix it?知道如何解决吗?
Looks like there is some interference going on.似乎有一些干扰正在发生。
I have found two workaround-solutions, it depends on what your desired effect is.我找到了两种解决方法,这取决于您想要的效果。
Idea: Using ZStack
so that ScrollView
and your header don't interfere.想法:使用
ZStack
以便ScrollView
和您的 header 不会干扰。
struct ContentView: View {
@State var largeHeader = true
var body: some View {
ZStack {
ScrollView {
VStack {
ForEach(0..<3) { i in
Text("Content\(i)")
.padding()
}
}
.background(GeometryReader { geometryProxy -> Color in
DispatchQueue.main.async {
largeHeader = geometryProxy.frame(in: .named("1")).minY >= 0
}
return Color.clear
})
}
.coordinateSpace(name: "1")
.offset(y: largeHeader ? 100 : 60)
VStack {
VStack {
Spacer()
Text("HEADER")
.padding()
Divider()
}
.frame(maxWidth: .infinity)
.frame(height: largeHeader ? 140 : 100)
.background(Color.white)
Spacer()
}
.edgesIgnoringSafeArea(.all)
}
.animation(.default)
}
}
The header of this one would always change the height, no matter how large the content-height is.这个 header 总是会改变高度,不管内容高度有多大。
Idea: Only change header height when there is enough content to scroll.想法:只有当有足够的内容滚动时才改变 header 高度。
Solution: Finding out the height of the scrollview-content.解决方案:找出滚动视图内容的高度。
struct ContentView: View {
@State var largeHeader = true
@State var scrollViewScrollable = false
var body: some View {
VStack {
Text("HEADER").padding(.vertical, largeHeader ? 30 : 10)
Divider()
ScrollView {
VStack {
ForEach(0..<3) { i in
Text("Content\(i)")
.padding()
}
}
.background(GeometryReader { geometryProxy -> Color in
if scrollViewScrollable {
DispatchQueue.main.async {
largeHeader = geometryProxy.frame(in: .named("1")).minY >= 0
}
}
return Color.clear
})
.background(
GeometryReader { proxy in
Color.clear.onAppear {
scrollViewScrollable = proxy.frame(in: .named("1")).size.height >= UIScreen.main.bounds.size.height - 100
}
}
)
}
.coordinateSpace(name: "1")
}
.animation(.default)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.