iOS Expand Button Tap Area
Override pointInside to Expand the Touch Area
In daily development, it’s common to have a UI layout that looks perfect according to the design, but the actual button touch areas are too small, making accurate taps difficult—especially unfriendly for users with larger fingers.

Completed example image
Before…
Regarding this issue, I didn’t research it deeply at first. I simply overlaid a larger transparent UIButton on the original button and used this transparent button to handle events. This approach is very troublesome and hard to manage when there are many components.
Later, the issue was solved by layout adjustments. The button’s top, bottom, left, and right constraints were set to 0 (or less) during layout, then the imageEdgeInsets, titleEdgeInsets, and contentEdgeInsets were controlled to push the icon/button title to the correct UI design position. However, this method is more suitable for projects using Storyboard/xib, as you can adjust the layout directly in Interface Builder. Another point is that the designed icon should preferably have no extra spacing; otherwise, positioning becomes difficult, sometimes stuck at a 0.5 distance that can’t be aligned properly.
After…
As the saying goes, the more you see, the more you know. Recently, after starting a new project, I learned a neat trick: you can enlarge the event response area in UIButton’s pointInside method. By default, it uses UIButton’s bounds, but you can extend the bounds inside to make the button’s clickable area larger!
After the above ideas… we can:
class MyButton: UIButton {
var touchEdgeInsets:UIEdgeInsets?
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
var frame = self.bounds
if let touchEdgeInsets = self.touchEdgeInsets {
frame = frame.inset(by: touchEdgeInsets)
}
return frame.contains(point);
}
}
Create a custom UIButton and add a public property touchEdgeInsets to store the expanded touch area for easy use; then override the pointInside method to implement the above idea.
Usage:
import UIKit
class MusicViewController: UIViewController {
@IBOutlet weak var playerButton: MyButton!
override func viewDidLoad() {
super.viewDidLoad()
playerButton.touchEdgeInsets = UIEdgeInsets(top: -10, left: -10, bottom: -10, right: -10)
}
}

Play button / Blue is the original touch area / Red is the expanded touch area
When using, just remember to set the Button’s Class to our custom MyButton, then you can expand the clickable area for each Button by setting touchEdgeInsets!
️⚠️⚠️⚠️⚠️️️️⚠️️️️
When using Storyboard/xib, remember to set the
Custom Classto MyButton
⚠️⚠️⚠️⚠️⚠️
touchEdgeInsetsexpands outward from (0,0) as the center, so the distances for top, bottom, left, and right must be negative to extend.
Looks good… but:
Replacing every UIButton with a custom MyButton is quite tedious and increases code complexity, which may cause conflicts in large projects.
For this feature that we believe every UIButton should have by default, if possible, we want to directly extend the original UIButton using an Extension:
private var buttonTouchEdgeInsets: UIEdgeInsets?
extension UIButton {
var touchEdgeInsets:UIEdgeInsets? {
get {
return objc_getAssociatedObject(self, &buttonTouchEdgeInsets) as? UIEdgeInsets
}
set {
objc_setAssociatedObject(self,
&buttonTouchEdgeInsets, newValue,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
var frame = self.bounds
if let touchEdgeInsets = self.touchEdgeInsets {
frame = frame.inset(by: touchEdgeInsets)
}
return frame.contains(point);
}
}
Usage as shown in the previous example.
Since Extensions cannot contain stored properties or they will cause a compile error “Extensions must not contain stored properties,” here we refer to Using Property with Associated Object to associate the external variable buttonTouchEdgeInsets with our Extension, allowing it to be used like a regular property. (For detailed explanation, please see Mao’s article)
What about UIImageView (UITapGestureRecognizer)?
For image taps and tap gestures added to the View,
you can achieve the same effect by overriding UIImageView’s pointInside method.
Done! After continuous improvements, solving this issue has become much simpler and more convenient!
References:
UIView Expand Touch Area (Objective-C)
Postscript
Around the same time last year, I wanted to create a subcategory “Small Things Lead to Big Things” to record daily trivial development tasks. These small tasks quietly add up and improve both the app’s experience and code quality. However, after delaying for a year, I finally added another article <(_ _)>. Small things are really easy to forget to document!



Comments