1 year ago
#57865
nickcoding2
Sliding card not showing transition from withAnimation { } block
so I have a sliding card located at the bottom of the page. When it appears, it starts with the top of edge of the card at about halfway up the screen. I want to make it so that when I tap it or swipe down, it dismisses by animating a transition of the card to the bottom edge of the screen. The problem I'm running into is this. When I'm running the withAnimation { } block, the card is dismissing immediately (instantly disappearing) instead of animating the change by moving off the screen smoothly. How can I fix this?
struct ContentView: View {
@ObservedObject var appState: AppState = AppState()
var body: some View {
ZStack {
Color.gray
Text("Main View")
SlideOverView(appState: appState, content: {
VStack {
Text("Slide Over View")
Spacer()
}
})
}
}
}
class AppState: NSObject, ObservableObject {
@Published var showCard: Bool = false
}
struct SlideOverView<Content> : View where Content : View {
@ObservedObject var appState: AppState
var content: () -> Content
init(appState: AppState, content: @escaping () -> Content) {
self.appState = appState
self.content = content
}
public var body: some View {
ModifiedContent(content: self.content(), modifier: CardView(appState: appState))
}
}
struct CardView: ViewModifier {
@ObservedObject var appState: AppState
@State private var dragging = false
@GestureState private var dragTracker: CGSize = CGSize.zero
func body(content: Content) -> some View {
let position: CGFloat = UIScreen.main.bounds.height * 0.4
return ZStack(alignment: .top) {
if appState.showCard {
ZStack(alignment: .top) {
RoundedRectangle(cornerRadius: 2.5)
.frame(width: 40, height: 5.0)
.foregroundColor(Color.secondary)
.padding(10)
content.padding(.top, 30)
}.transition(.asymmetric(insertion: .move(edge: .top), removal: .move(edge: .bottom)))
.frame(minWidth: UIScreen.main.bounds.width)
.scaleEffect(x: 1, y: 1, anchor: .center)
.background(Color.white)
.cornerRadius(15)
}
}
.offset(y: max(0, position + self.dragTracker.height))
.animation({
Animation.interpolatingSpring(stiffness: 250.0, damping: 40.0, initialVelocity: 5.0)
}())
.gesture(DragGesture()
.updating($dragTracker) { drag, state, transaction in state = drag.translation }
.onChanged {_ in dragging = true }
.onEnded(onDragEnded))
.onTapGesture {
let low: CGFloat = UIScreen.main.bounds.height * 0.4
if position == low {
withAnimation {
appState.showCard = false
}
}
}
}
private func onDragEnded(drag: DragGesture.Value) {
dragging = false
let dragDirection = drag.predictedEndLocation.y - drag.location.y
if dragDirection > 0 {
withAnimation {
appState.showCard = false
}
}
}
}
swift
animation
swiftui
gesture
uiswipegesturerecognizer
0 Answers
Your Answer