How can I increase the Tap Area for UIButton?

I use UIButton with auto layout. When images are small the tap area is also small. I could imagine several approaches to fix this:

  1. increase the image size, i.e., place a transparent area around the image. This is not good because when you position the image you have to keep the extra transparent border in mind.
  2. use CGRectInset and increase the size. This does not work well with auto layout because using auto layout it will fall back to the original image size.

Beside the two approaches above is there a better solution to increase the tap area of a UIButton?


You can simply adjust the content inset of the button to get your desired size. In code, it will look like this:

button.contentEdgeInsets = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
//Or if you specifically want to adjust around the image, instead use button.imageEdgeInsets

In interface builder, it will look like this:

interface builder


Very easy. Create a custom UIButton class. Then override pointInside... method and change the value as you want.

#import "CustomButton.h"

@implementation CustomButton

-(BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGRect newArea = CGRectMake(self.bounds.origin.x - 10, self.bounds.origin.y - 10, self.bounds.size.width + 20, self.bounds.size.height + 20);
    
    return CGRectContainsPoint(newArea, point);
}
@end

It will take more 10 points touch area for every side.

And Swift 5 version:

class CustomButton: UIButton {
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return bounds.insetBy(dx: -10, dy: -10).contains(point)
    }
}

I confirm that Syed's solution works well even with autolayout. Here's the Swift 4.x version:

import UIKit

class BeepSmallButton: UIButton {

    // MARK: - Functions

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        let newArea = CGRect(
            x: self.bounds.origin.x - 5.0,
            y: self.bounds.origin.y - 5.0,
            width: self.bounds.size.width + 10.0,
            height: self.bounds.size.height + 20.0
        )
        return newArea.contains(point)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}