Sebastian Faltoni Software Architect. Passionate about Clean Code, Tech, Web, AI, .NET, Python, IOT, Swift, SwiftUI and also Blazor

Fix: SwiftUI Button or TapGesture inside ZStack tap area is shifted down

1 min read

While a was developing a prototype UX with SwiftUI I have noticed a strange behavior. A button click or any Element with a onTapGesture, didn’t get hit when tapped, you had to tap a bit more down outside the expected hit area. My UX was composed by ZStack which had inside an image filling the ZStack area and a small button acting as a back button. The ZStack was inside a List but even without the list, the behavior didn’t change. It was something like this.

This is a snippet taken from my code.

      List {
            ZStack {
                URLImage(URL(string: pictureUrl)!)
                    .frame(minWidth: 100.0,  minHeight: 250.0, maxHeight: 250.0)
                    .clipped()
            }
            
            VStack {
                Image(systemName: "lessthan")
                    
                    .resizable()
                    .scaledToFill()
                    .padding(10)
                    .frame(width: 40, height: 40)
            }
            .frame(width: 40, height: 40)
            .foregroundColor(Color.black)
            .background(Color.white)
            .contentShape(Circle())
            .clipShape(Circle())
            .shadow(radius: 0.5)
            .opacity(0.5)
            .onTapGesture {
                self.presentationMode.wrappedValue.dismiss()
            }
        }
        .navigationBarHidden(true)
        .navigationBarBackButtonHidden(true) 
        .edgesIgnoringSafeArea(.all)
        .onAppear(perform: {
            self.viewModel.refresh(id: self.itemId)
        })

The above code was inside a component has you can see what i was trying to achieve is to have my picture go behind the notch by ignoring the safe area.

While the UI is rendered correctly if you now try to tap on the back button, you won’t be able to do so. Why?! because the tappable area is shifted down a bit.

It took me hours to realize where the issue is, basically after trying to removing modifiers I noticed that some space was still taken from something, and then I realized what if I set an empty title?

Boom! it worked straight away now the hit test area is assigned correctly. Basically you just need to add the following modified after you set to hide the back button.

.navigationBarTitle("")

SwiftUI is amazing but is a young framework and sometimes you can find some difficulties but overall it’s amazing how fast you can build beautiful UI.

Let me know if you found this helpfull, and maybe if you liked it shared it with your friends, thank you!

Sebastian Faltoni Software Architect. Passionate about Clean Code, Tech, Web, AI, .NET, Python, IOT, Swift, SwiftUI and also Blazor

Leave a Reply

Your email address will not be published. Required fields are marked *