0

I have created a bottom card with a drag gesture that is not yet finished. But I ran into an issue when I set the default translation height from zero and it just jumps to what I think is translation 0.

import SwiftUI

struct TimetableBottomCardView: View {
    @State var translation: CGSize = CGSize(width: .zero, height: 785)
    var body: some View {
            VStack {
                TimetableBottomCardUI()
                Spacer()
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Material.ultraThick)
                .mask(RoundedRectangle(cornerRadius: 35).ignoresSafeArea(.all, edges: .bottom))
                .offset(y: translation.height)
                .gesture(
                DragGesture()
                    .onChanged { value in
                        translation = value.translation
                    }
                    .onEnded { value in
                        withAnimation {
                            let DefaultTranslation: CGSize = CGSize(width: .zero, height: 785)
                            translation = DefaultTranslation
                        }
                    }
            )
    }
}

struct TimetableBottomCardView_Previews: PreviewProvider {
    static var previews: some View {
        TimetableBottomCardView()
            .background(.blue)
    }
}
grandsirr
  • 584
  • 4
  • 19
Ash
  • 81
  • 9
  • Can you rewrite your question with more explanation, images, and gifs, and with a better title/explanation, please? – grandsirr Oct 20 '22 at 18:04

1 Answers1

1

You are assigning your transition value when your DragGesture changes. When you use onChanged, its value gives you a relative position, rather than an absolute one. That means your transition value only changes depending on where your last touch appeared, so as you're offsetting your view by 785, when onChanged gets triggered your view jumps up due to DragGestures relative value.

bug

As you can see here, your offset was 785, but when onChanged gets triggered, it sets it to 0, which means, it also sets its offset to zero

To avoid this behavior, you have to add your offset amount (785) to your card so that you can save your previous offset.

Result:

result

Code:

import SwiftUI

struct TimetableBottomCardView: View {
    @State var translation: CGSize = CGSize(width: .zero, height: 785)
    var body: some View {
            VStack {
                Text("Draggable Card")
                    .frame(width: 300, height: 300)
                    .background(.teal)
                Spacer()
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Material.ultraThick)
                .mask(RoundedRectangle(cornerRadius: 35).ignoresSafeArea(.all, edges: .bottom))
                .offset(y: translation.height)
                .gesture(
                DragGesture()
                    .onChanged { value in
                        print(value.translation)
                        translation = CGSize(width: value.translation.width, height: value.translation.height + 785)
                    }
                    .onEnded { value in
                        withAnimation {
                            let DefaultTranslation: CGSize = CGSize(width: .zero, height: 785)
                            translation = DefaultTranslation
                        }
                    }
            )
                .onChange(of: translation) {_ in
                    // print(translation)
                }
    }
}

struct TimetableBottomCardView_Previews: PreviewProvider {
    static var previews: some View {
        TimetableBottomCardView()
            .background(.blue)
    }
}
grandsirr
  • 584
  • 4
  • 19