我试图在SwiftUI中复制钱包应用的滚动行为。具体地说,我希望实现这样的效果,即在卡片视图上一直向上滚动返回到主视图。
为了实现这一点,我实现了以下代码:
struct ContentView: View {
@State private var isCardVisible = true
@State private var dragOffset: CGFloat = 0
var body: some View {
ZStack {
Color.gray.ignoresSafeArea()
if isCardVisible {
ScrollView {
VStack(spacing: 20) {
Text("Card View")
.font(.largeTitle)
.padding()
.background(Color.white)
.cornerRadius(8)
.offset(y: max(dragOffset, 0))
.gesture(
DragGesture()
.onChanged { value in
dragOffset = value.translation.height
}
.onEnded { value in
if dragOffset < -200 {
isCardVisible = false
} else {
dragOffset = 0
}
}
)
}
.padding()
}
.overlay(
GeometryReader { geometry in
Color.clear
.preference(key: OffsetPreferenceKey.self, value: geometry.frame(in: .global).origin.y)
}
)
.onPreferenceChange(OffsetPreferenceKey.self) { offset in
if offset < -200 {
isCardVisible = false
}
}
}
if !isCardVisible {
Button("Show Card") {
isCardVisible = true
}
.padding()
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(8)
}
}
}
}
struct OffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
在我的实现中,我使用ZStack
来对视图进行分层。卡视图显示在ScrollView
内,可以向上或向下滚动。dragOffset
状态变量用于跟踪拖动时卡片视图的垂直平移。
为了处理退出行为,我在卡片视图上使用了一个DragGesture
。当用户向上滚动并释放手指时,onEnded
闭包会检查dragOffset
是否小于-200
。如果是,则isCardVisible
状态设置为false
,卡视图将被隐藏。
此外,我还使用GeometryReader
来检测卡片视图的滚动偏移量。OffsetPreferenceKey
用于存储和跟踪偏移量值,onPreferenceChange
修饰符用于检查偏移量是否小于-200
,从而触发退出行为。
尽管我做了很多努力,但滚动行为与钱包应用程序中看到的预期效果不匹配。我已经附上了我已经实现的代码沿着这个问题。
有没有人可以提供指导,如何修改此代码,以准确地复制钱包应用程序的滚动行为,其中向上滚动所有的方式返回到主视图?谢谢你!
1条答案
按热度按时间emeijp431#
你的问题和代码表明你在这方面做了很多研究。不幸的是,您试图将您发现的所有内容合并到这一视图中。你遇到的第一个问题是你不能同时拥有一个垂直的
ScrollView
和一个垂直的DragGesture
。这不管用第二,DragGestures
和PreferenceKeys
实际上不能像这样一起工作。在这种情况下,您甚至不需要DragGesture
,只需要PreferenceKey
。第三,不要在ScrollView
中的视图上放置偏移量,否则会改变视图的垂直位置。如果DragGesture
偶尔能工作,你的视图就会上下跳动。让ScrollView
来处理这个问题。下面注解代码:最后,将卡片放回原处的实际动画被称为“英雄动画”,它使用
MatchedGeometry
效果。谷歌,你会发现很多关于使用它的教程。