gpt4 book ai didi

animation - SwiftUI - 滚动上的隐藏/折叠部分

转载 作者:行者123 更新时间:2023-12-03 14:32:53 27 4
gpt4 key购买 nike

我一直在寻找一种方法来复制 Airbnb 和许多其他公司所做的滚动动画,即 View 的顶部在滚动时折叠/隐藏,并在用户再次开始向上滚动时立即重新出现。请注意“日期”和“访客”按钮在附加图像中滚动时如何变透明。

AirBnB

下面我附上了一个简单的 View ,我只是把它放在一起。我已经尝试包括我想要在 ScrollView 内部和外部折叠的区域。我猜它需要在 ScrollView 之外,因为它会独立于您在滚动区域内的位置进行动画处理。

import SwiftUI

struct HideScrollView: View {
var body: some View {
ScrollView {
HStack {
Text("Hide Me")
Spacer()
}.padding(.horizontal) .frame(height: 60) .background(Color.red) .foregroundColor(Color.white)
ForEach(0 ..< 20) { item in
VStack {
HStack {
Text("Content Items")
Spacer()
}.padding(.horizontal) .frame(height: 40)
}
}
}

}

}

最佳答案

由于没有像 didScroll 或任何这样的 ScrollView 的委托(delegate),因此有两种方法可以实现所需的结果。
#1 您应该实现 DragGesture 手势,这不是首选方式,因为不会同时调用手势。

.simultaneousGesture(DragGesture().onChanged({ transition in
if transition.translation.height > 0{
withAnimation{
self.viewIsShown = true
}
} else {
withAnimation{
self.viewIsShown = false
}
}
})
)
#2 首选方式:根据 Martin's tutorial , 你应该使用 GeometryReader里面 ScrollView作为第一个 child ,这使您有可能获得 GeometryReader 中元素的确切位置, 像这样:
ScrollView(.vertical, showsIndicators: false) {
GeometryReader { geometry in
Color.clear.preference(key: OffsetKey.self, value: geometry.frame(in:.global).minY).frame(height: 0)
}
//Your scrollable content here
}

添加您的偏好键,它符合 PreferenceKey 协议(protocol):
struct OffsetKey: PreferenceKey {
static let defaultValue: CGFloat? = nil
static func reduce(value: inout CGFloat?, nextValue: () -> CGFloat?) {
value = value ?? nextValue()
}
}
读取偏好键中设置的值,为此添加 .onPreferenceChange(OffsetKey.self)到 ScrollView 或任何它的父 View 。
你应该有 @State两者的包装 initialOffestoffset .
.onPreferenceChange(OffsetKey.self) {
if self.initialOffset == nil || self.initialOffset == 0 {
self.initialOffset = $0
//setting initialOffest when view first appeared.
}
self.offset = $0

}
检查 initialOffset 之间的差异和 offset将告诉您 View 的滚动状态。如果 initialOffset高于 offset然后你的 View 向下滚动,你应该隐藏你想要的 View 。
根据您发布的代码,它应该如下所示:
struct HideScrollView: View {

@State var initialOffset: CGFloat?
@State var offset: CGFloat?
@State var viewIsShown: Bool = true

var body: some View {

VStack{
HStack {
Text("Hide Me")
Spacer()
}.padding(.horizontal) .frame(height: 60) .background(Color.red) .foregroundColor(Color.white).opacity(self.viewIsShown ? 1 : 0)

ScrollView {

GeometryReader { geometry in
Color.clear.preference(key: OffsetKey.self, value: geometry.frame(in: .global).minY)
.frame(height: 0)
}

ForEach(0 ..< 20) { item in
VStack {
HStack {
Text("Content Items")
Spacer()
}.padding(.horizontal) .frame(height: 40)
}
}
}
}.onPreferenceChange(OffsetKey.self) {
if self.initialOffset == nil || self.initialOffset == 0 {
self.initialOffset = $0
}

self.offset = $0

guard let initialOffset = self.initialOffset,
let offset = self.offset else {
return
}


if(initialOffset > offset){
self.viewIsShown = false
print("hide")
} else {
self.viewIsShown = true
print("show")
}



}

}
}

struct OffsetKey: PreferenceKey {
static let defaultValue: CGFloat? = nil
static func reduce(value: inout CGFloat?,
nextValue: () -> CGFloat?) {
value = value ?? nextValue()
}
}

关于animation - SwiftUI - 滚动上的隐藏/折叠部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57494495/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com