29
votes

I've built a custom slider in SwiftUI with a thumb dragger that is 20x20. Everything is working, except the tap target is quite small since it's just the 20x20 view. I'm looking for a way to increase this to make it easier for users to interact with my slider. Is there a way to do this in SwiftUI?

I tried wrapping my thumb in Color.clear.overlay and setting the frame to 60x60. This works if the color is solid, like red, but with clear the tap target seems to revert back to visible pixels of 20x20.

You can see on this gif I'm able to drag the slider even when clicking outside of the thumb.

slider with red background

However, as soon as I change the color to clear, this area no longer receives interactions.

slider with clear background

3
clear background are untouchable in swift UI, I asked a question similar to this not long ago - I'd recommend putting a button behind it and making the background colour the same as the colour behind it instead of clear - Quinn
my question for reference: stackoverflow.com/questions/57191013/… - Quinn
Here I just showed grey, but I want to show multiple colors in the background of the slider so it won't be a solid color. - keegan3d
that's too bad - I think this is just a swiftUI issue, you can submit a bug report, hopefully eventually they allow you to tap on clear things but right now I'm not sure what you can do - Quinn
another option might be to add a background that isn't technically clear, but the alpha is so low that it isn't noticeable - though I'm not sure if you would be able to make it 100% unnoticeable - Quinn

3 Answers

44
votes

Add a .contentShape(Rectangle()) after the frame.

13
votes

I'm sure there is several ways to skin the cat, but this is how i made a big button with the whole area tappable:

Button(action: { someAction() }, label: {
                Text("OK")
                .frame(minWidth: 200)
                .contentShape(Rectangle())
                .padding()
            })
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(5.0)
0
votes

I had the same problem. Except I didn't want the expanded overlay to impact the rest of the layout. If you embed everything in a ZStack and put a rectangle before your interactive object, you can control the size of the gesture. Kind of like this:

Rectangle().frame(width: screen.width, height: 300).opacity(0.001)
                    .layoutPriority(-1)

Just needed to make sure to set the opacity to next to nothing so you can't see it, and the layout priority to -1 so it doesn't impact the view.