coco
coco

Reputation: 3136

SwiftUI image with borders overlaying button

Thanks to a previous question I asked, I am using Color.black.overlay and .clipped() to show an image with letterbox borders above and below it.

But when I attempt to put a button on the top border, it can't be tapped on (I assume because the image (unclipped) is in that space, and is intercepting the tap gesture).

Here is what the layout looks like:

enter image description here

Here is the code:

    var body: some View {
        ZStack {
            Color.black
            VStack {
                topBorder
                imageMiddle
                bottomBorder
            }
        }
        .ignoresSafeArea()
    }
    
    var topBorder: some View {
        return Group {
            ZStack {
                Rectangle()
                    .fill(.green)
                    .frame(minHeight: borderHeight, maxHeight: borderHeight)
                Button {
                    print("tap")
                } label: {
                    Image(systemName: "hand.tap.fill")
                        .foregroundColor(.black)
                }
            }
        }
    }
    
    var bottomBorder: some View {
        return Group {
            Rectangle()
                .fill(.green)
                .frame(minHeight: borderHeight, maxHeight: borderHeight)
        }
    }
    
    var imageMiddle: some View {
        return Group {
            Color.black.overlay(
                Image("cat")
                    .scaledToFill()
            )
            .clipped()
        }
    }

How can I expose that button to a user's tap?

Upvotes: 0

Views: 442

Answers (1)

bjorn.lau
bjorn.lau

Reputation: 1178

Adding .allowsHitTesting(false) to your image view will fix it. However, it seems like the wrong approach.

VStack {
    topBorder
    imageMiddle
        .allowsHitTesting(false) // <- This will fix your problem.
    bottomBorder
}

I would recommend using another approach to add your borders on top of the image instead. Something like this:

ZStack {
    imageMiddle
    VStack {
        topBorder
            .overlay(alignment: .bottom) {
                Rectangle().frame(minHeight: 0, maxHeight: 10)
            }
        Spacer()
        bottomBorder
            .overlay(alignment: .top) {
                Rectangle().frame(minHeight: 0, maxHeight: 10)
            }
    }
}
.ignoresSafeArea()

Upvotes: 1

Related Questions