Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gesture blocking buttons in ZStack

I have a gesture added to a Rectangle inside a ZStack. I have a VStack which is a view or menu of buttons. When I add the gesture to the Rectangle (because I need to detect a tap on that view behind the menu buttons), then the buttons can not receive interaction from the user on device. I have the Rectangle behind the buttons and they do show above the Rectangle. On the simulator it worked just fine but on device it does not. Any help would be greatly appreciated from the community. Thanks!

var body: some View {
        ZStack {
            Rectangle()
                .foregroundColor(Color.black.opacity(0.01))
                .gesture(DragGesture(minimumDistance: 0)
                    .onChanged({ (value) in
                    self.store.tapped = true
                }))
            VStack(alignment: .leading, spacing: 0) {
                //menu buttons
                HStack(alignment: .center, spacing: 18.5) {
                    someView()
                        .environmentObject(self.anotherStore)
                        .frame(width: 145, height: 22)
                    self.otherSubviews()
                }
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 37, alignment: .leading)
                .padding(EdgeInsets(top: 0, leading: 6, bottom: 0, trailing: 6))
                //menu detail view
                self.detailView()
                }
            .padding(EdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 12))
        }
    }

I have tried changing the .zIndex for both to -1 for the Rectangle to something higher for the menu view. It does not change anything

I would like for the Rectangle to receive interaction (taps) from the user and also that the VStack of buttons will also receive interaction from the user.

like image 473
Nick Perkins Avatar asked Jan 01 '23 13:01

Nick Perkins


1 Answers

Figured out that with a view in the background that has a gesture you need to make sure that your other views have .contentShape(Specify A Shape).

In the Apple documentation it states

    /// Returns a new view that defines the content shape for
    /// hit-testing `self` as `shape`.

I added .contentShape(Rectangle()) to the VStack and it allowed taps for the menu view of buttons as well as allowing taps to the Rectangle view in the background.

Updated code with answer

var body: some View {
        ZStack {
            Rectangle()
                .foregroundColor(Color.black.opacity(0.01))
                .gesture(DragGesture(minimumDistance: 0)
                    .onChanged({ (value) in
                    self.store.tapped = true
                }))
            VStack(alignment: .leading, spacing: 0) {
                //menu buttons
                HStack(alignment: .center, spacing: 18.5) {
                    someView()
                        .environmentObject(self.anotherStore)
                        .frame(width: 145, height: 22)
                    self.otherSubviews()
                }
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 37, alignment: .leading)
                .padding(EdgeInsets(top: 0, leading: 6, bottom: 0, trailing: 6))
                //menu detail view
                self.detailView()
                }.contentShape(Rectangle()) //Define a tappable area
            .padding(EdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 12))
        }
    }
like image 169
Nick Perkins Avatar answered Jan 12 '23 02:01

Nick Perkins