jnrkane
jnrkane

Reputation: 1

How can I use partial DragGesture for my side menu

I'm trying to use the DragGesture for my side menu. Currently, the DragGesture is using the entire screen, and I'd like to use it only from the left to right as shown in the screenshot (gray area):

My code snippet:

@State var width = UIScreen.main.bounds.width - 65
@State var x = -UIScreen.main.bounds.width + 65

var body: some View {
    
    ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
        HomePage(x: $x)
        SlideMenu()
            .shadow(color: Color.black.opacity(x == 0 ? 0.2 : 0), radius: 5, x: 5, y:0)
            .offset(x: x)
            .background(Color.gray.opacity(x == 0 ? 0.2 : 0).ignoresSafeArea(.all, edges: .vertical).onTapGesture {
                withAnimation {
                    
                    x = -width
                }
            })
    }
    .gesture(DragGesture().onChanged({ (value) in
        withAnimation {
            if value.translation.width > 0 {
                if x < 0 {
                    x = -width + value.translation.width
                }
            }
            else {
                x = value.translation.width
            }
        }
    }).onEnded({ (value) in
        withAnimation {
            if -x < width / 2 {
            x = 0
            }
            else {
                x = -width
            }
        }
    }))
}

Upvotes: 0

Views: 318

Answers (1)

Phil Dukhov
Phil Dukhov

Reputation: 87914

You can check gesture startLocation and ignore it, if it's out of your desired rect

struct ContentView: View {
    @State var width = UIScreen.main.bounds.width - 65
    @State var x = -UIScreen.main.bounds.width + 65
    let gestureMaxScreenOffset: CGFloat = 100

    var body: some View {
        ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
            Text("HomePage(x: $x)")
                .onTapGesture {
                    print("hello")
                }
            Text("SlideMenu()")
                .fillMaxSize()
                .shadow(color: Color.black.opacity(x == 0 ? 0.2 : 0), radius: 5, x: 5, y: 0)
                .offset(x: x)
                .background(Color.gray.opacity(x == 0 ? 0.2 : 0).ignoresSafeArea(.all, edges: .vertical).onTapGesture {
                    withAnimation {

                        x = -width
                    }
                })
        }.gesture(DragGesture().onChanged({ (value) in
            withAnimation {
                if value.startLocation.x > gestureMaxScreenOffset {
                    return
                }
                if value.translation.width > 0 {
                    if x < 0 {
                        x = -width + value.translation.width
                    }
                } else {
                    x = value.translation.width
                }
            }
        }).onEnded({ (value) in
            if value.startLocation.x > gestureMaxScreenOffset {
                return
            }
            withAnimation {
                if -x < width / 2 {
                    x = 0
                } else {
                    x = -width
                }
            }
        }))
    }
}

Upvotes: 1

Related Questions