32

Tap registering beyond clipped view bounds.

It seems SwiftUI will layout an image in its full width and height inside of another view to give it a fill mode of aspect fill. That is fine but if I want to add a tap action to the view the tap registers outside the bounds of the view even when clipped. I may be doing this wrong or there may be another way. In addition to this code I have tried using .clippedShape and .contentShape of rectangle. How do I get it to where taps outside the clipped frame do not register on the underlying image. To reproduce switch to clip and tap in the area the image would occupy outside the frame of the clipped view.

import SwiftUI

struct ImageContainer : View {
    var body: some View {
        Image(systemName: "cube")
        .resizable()
        .scaledToFill()
        .clipped()
    }
}

struct ContentView: View {
    @State var isClipped = false
    @State var count = 0

    var body: some View {
        VStack{
            Toggle(isOn: $isClipped) {
                Text("Clip It ")
                .font(.title)
            }.frame(width: 175)
            ZStack{
                if self.isClipped == true{
                    ImageContainer()
                        .frame(width: 200, height: 200)
                        .contentShape(Rectangle())
                        .clipped()

                        .background(Color.blue)
                        .onTapGesture {
                            print("tapped mainContainer\(self.count)\n")
                            self.count += 1
                        }
                }else{
                    ImageContainer()
                        .frame(width: 200, height: 200)
                        .background(Color.blue)
                         .onTapGesture {
                            print("tapped mainContainer\(self.count)\n")
                            self.count += 1
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
agibson007
  • 4,173
  • 2
  • 19
  • 24
  • For a more extreme test example make each frame greater for example 300 and you will see touching outside the clipped leading and trailing edges still activates – agibson007 Nov 21 '19 at 16:23
  • 2
    Any luck with this? I'm baffled that this works like this and that there aren't more people asking this question – Roland Jul 19 '20 at 16:18
  • Just saw this, might be helpful: https://stackoverflow.com/questions/57013933/clipped-image-calls-tapaction-outside-frame – Roland Jul 19 '20 at 16:40
  • @Roland I will check that out. I have not built anything with SwiftUI in a bit but I could not believe this was never figured out. I had a bug report into Apple as well. – agibson007 Jul 19 '20 at 18:59
  • 2
    This is still an issue over three years later, just experienced this bug on WatchOS 9. – danfordham Jan 08 '23 at 18:29

2 Answers2

27

I've had success using .contentShape(Rectangle()) on the image which controls the tappable area.

You can try using ZIndex so surrounding views capture the hit. But I have had mixed results with that, AFAIK that's buggged too as of iOS 14.1

Olcay Ertaş
  • 5,987
  • 8
  • 76
  • 112
Miguel Lomelí
  • 1,224
  • 1
  • 10
  • 17
0

For some reason , .contentShape() method only work for tap gesture, but probably not work for textfield and TextEditor .

You can use zindex(0) in image view, zindex(1...) in your target view

Haolong
  • 31
  • 5