Evan
Evan

Reputation: 2040

Detecting tap gesture on the background of a GeometryReader SwiftUI

I have a main view, and, within that view I have a little pop-up menu that is within a GeometryReader, like this:

        if (self.show){
                GeometryReader{_ in
                    Menu()
                }.background(Color.black.opacity(0.65))
        }

the line ~~~.background(Color.black.opacity(0.65))~~~ is essentially making the background (i.e. every part of the view that isn't in the pop up view, a bit dark. I would like to do something like this:

        if (self.show){
                GeometryReader{_ in
                    Menu()
                }.background(Color.black.opacity(0.65))
                    .background(.onTapGesture{
                        print("asdf")
                        })
        }

but this syntax isn't supported. Is there any way I can accomplish this? Essentially, I want it so that when I click outside of the GeometryReader, I can toggle a variable (in this case, get rid of the pop up view).

I tried just making a TapGesture Recognizer on the main view, but since the GeometryReader is part of the main view, when I tap on the GeometryReader pop up view itself, then it disappears.

Is there any way to accomplish something similar to the code I wrote above?

Thanks

Upvotes: 2

Views: 4443

Answers (2)

Shahriyar
Shahriyar

Reputation: 688

Another possible approach is to add a onTapGesture modifier on your background.

GeometryReader { geometry in
    // YOUR VIEWS
}
.background(content: {
    Color.black.opacity(0.2)
        .onTapGesture {
            shouldShow.toggle()
        }
})

Upvotes: -1

KlausM
KlausM

Reputation: 291

Here is an example. I use three tapGestures:

  • one on the Main View to toggle the "Menu"
  • one on the "Menu" (do something there)
  • and one on the Background View to dismiss the "Menu" again, like so:
    struct ContentView: View {
        
        @State private var showMenu: Bool = false
        
        var body: some View {
            ZStack {
                
                // The Main View.
                Text("Tap Me!")
                    .padding()
                    .onTapGesture {
                        showMenu.toggle()
                        print("Tapped Main View")
                    }
                
                // The Menu View (shown on top of the Main View).
                if showMenu {
                    GeometryReader { _ in
                        Text("Menu")
                            .padding()
                            .onTapGesture {
                                // do something here
                                print("Tapped Menu")
                            }
                    }
                    
                    // The Background View that darkens the whole screen.
                    .background(
                        Color.gray.opacity(0.2)
                            .edgesIgnoringSafeArea(.all)
                    )
                    .onTapGesture {
                        showMenu.toggle()
                        print("Tapped Background")
                    }
                }
            }
        }
    }

A tap on the "Tap Me!" (main view) brings up the menu view. The "Menu" captures taps to act upon - do whatever you want to do there.

Whenever the user taps outside of the "Menu" the tapGesture on the background recognizes the tap and dismisses the "Menu" including the darkening background --> the main view lightens again.

Upvotes: 2

Related Questions