0

I have a gesture applied to my text. Right now, it is sitting at the bottom of the screen and if I drag it to anywhere and let go, it goes back to the bottom. But if I drag it to the top half of my device screen, it should stay at the top.

The feature is almost ready to go, it just needs the correct function to split using UIScreen.main.bounds.

struct SwiftUIView: View {
    @State var offset: CGSize = .zero
    @State var isOnTop = false
    var body: some View {
        Text("Hello!")
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: isOnTop == true ? .top : .bottom)
            .offset(offset)
            .gesture(
                DragGesture()
                    .onChanged { value in
                        withAnimation(.spring()) {
                            offset = value.translation
                        }
                    }
                    .onEnded { value in
                        withAnimation(.spring()) {
                            offset = .zero
                            // if dragged to the top half of the screen, set true
                            //isOnTop = true
                        }
                    }
            )
    }
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116

1 Answers1

0

This is how I will do, I use GeometryReader to have the size of my screen and I will apply logic to my offset when my gesture is ended

struct SwiftUIView: View {


@State private var yOffset: CGFloat = 0.0
@State private var xOffset: CGFloat = 0.0
@State private var height: CGFloat = 0
@State private var lastXOffset: CGFloat = 0.0
@State private var lastYOffset : CGFloat = 0.0


var body: some View {
    GeometryReader{ geo in
            VStack{
                Spacer()
                Text("Hello!")
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
                    .offset(x: xOffset, y: yOffset >= 0 ? 0: yOffset)
                .gesture(DragGesture().onChanged({ gesture in
                    self.xOffset = gesture.translation.width + lastXOffset
                    self.yOffset = gesture.translation.height + lastYOffset
                    
                }).onEnded({ _ in
                    withAnimation{
                        lastXOffset = xOffset
                        if yOffset <= -height/2 {
                            yOffset = -height + geo.safeAreaInsets.top
                            
                            ///save last offset
                            lastYOffset = yOffset
                            
                        } else {
                            yOffset = 0
                            ///save last offset
                            lastYOffset = yOffset
                            
                        }
                    }
                }))
            }
        .onAppear{
            height = geo.size.height
        }
    }
}
}

enter image description here

AdR
  • 572
  • 1
  • 4
  • 13
  • This isn't what I wanted, your solution always aligns to the bottom. I just want a simple alignment like: If dragged & dropped somewhere in the bottom half of the display, `alignment: .bottom` and if dropped somewhere in the top half: `alignment: .top` – JackSparrow135 Feb 06 '23 at 19:31
  • a little offtopic.. how did you record the iphone screen to add it into a stackoverflow answer? – Iskandir Feb 07 '23 at 08:10
  • we must not understand each other well, in my solution when the Text is equal to or greater than half the screen it aligns vertically at the top and when it is less than or equal to half the screen it aligns vertically bottom – AdR Feb 07 '23 at 14:20
  • I take a screenshot and I convert the video to gif with https://ezgif.com/video-to-gif – AdR Feb 07 '23 at 14:21