Expand SwiftUI button tap area over the button frame
Asked Answered
A

3

9

I read a similar question about that issue. But that only expand the button size use .padding(). The red region in the snapshot is the tappable area.

The trailing padding to screen edge inserted by SwiftUI.framework can not be removing (I think). That causes any tap in the right edge of the screen can not trigger button action. How can I make the tappable area beyond the button size? So that user could tap that button more easier.

Thanks.

enter image description here

.navigationBarItems(trailing:
    Button(action: {
        self.context.isSheetDisplay = true
    }, label: {
        Image(systemName: "square.and.pencil")
            .font(.system(size: 20))
    })
    .padding([.leading, .top, .bottom])
    .background(Color.red)
)

Update:

e.g. The Photos.app in simulator could trigger tap at the edge. enter image description here

Aeolic answered 20/5, 2020 at 11:19 Comment(2)
It is a known SwiftUI bug and all proposed are just workarounds. If you want UIKit behaviour then use UIKit for now.Petra
The .contentShape(_:) says: Defines the content shape for hit testing. I try to use that modifier to expand the hit test area. But not success. We really need more documentation and code sample. :)Aeolic
F
1

The hit test area includes the background, but only when it isn’t clear. If your button is overlaying an area with a uniform background, you can make its background not clear, while still not noticeable to the user, by setting its background to the background color.

Button(…)
    .background(.background)
Fixer answered 18/4, 2022 at 19:4 Comment(0)
M
0

My solution to this issue for iOS is to add a nearly transparent background color ViewModifier to the button as part of a ButtonStyle:

import SwiftUI

struct ExampleBigPaddedButton: View {
    var body: some View {
        Button("Tap anywhere inside") {
            print("Tapped")
        }.buttonStyle(BigPaddedButtonStyle())
    }
}

struct BigPaddedButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        return configuration
            .label
            .foregroundColor(configuration.isPressed ? .gray : .black)
            .padding(EdgeInsets(top: 75, leading: 25, bottom: 75, trailing: 25))
            .background(Color(red: 1, green: 1, blue: 1, opacity: 0.01))
            .background(Rectangle().stroke(Color.gray))
    }
}

struct ExampleBigPaddedButton_Previews: PreviewProvider {
    static var previews: some View {
        ExampleBigPaddedButton()
    }
}

This produces a button having any size of padding you need that is tappable anywhere within its bounds.

Murcia answered 1/9, 2020 at 23:33 Comment(0)
F
0

So basically you need to give the label of the Button a padding and then give the button an offset with this padding. This is how I did it:

Button {
    print("Tapped")
} label: {
    Image(systemName: "xmark.circle.fill")
        .foregroundColor(.grayColor.opacity(0.7))
        .padding(EdgeInsets(top: 15, leading: 15, bottom: 15, trailing: 15))
}
.background(.red) // Shows the tappable area
.offset(x: 20, y: -20)
Floozy answered 22/1, 2023 at 21:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.