You can add a computed property
to your extension which you can set in your controller if you want to enable the hit area like this:
fileprivate let minimumHitArea = CGSize(width: 100, height: 100)
extension UIButton {
var isIncreasedHitAreaEnabled: Bool {
get {
// default value is false, so you can easily handle from outside when to enable the increased hit area of your specific button
return false
}
set {
}
}
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
// only if it's true the hit area can be increased
if isIncreasedHitAreaEnabled {
// increase the hit frame to be at least as big as `minimumHitArea`
let buttonSize = self.bounds.size
let widthToAdd = max(minimumHitArea.width - buttonSize.width, 0)
let heightToAdd = max(minimumHitArea.height - buttonSize.height, 0)
let largerFrame = self.bounds.insetBy(dx: -widthToAdd / 2, dy: -heightToAdd / 2)
// perform hit test on larger frame
return (largerFrame.contains(point)) ? self : nil
}
return self
}
}
And then in your view controller just set isIncreasedHitAreaEnabled
to true
if you want to increase it for a specific button (e.g. in your viewDidLoad
):
override func viewDidLoad() {
super.viewDidLoad()
specialButton.isIncreasedHitAreaEnabled = true
}
Update:
First of all the method which you use doesn't work like expected. And also my approach with the computed property
did not work like I thought. So even if the method does not work like expected, I just want to update my approach with the computed property
.
So to set the property from outside, you can use Associated Objects. Also have look here. With this solution now it would be possible to handle the Bool
property isIncreasedHitAreaEnabled
from your controller:
fileprivate let minimumHitArea = CGSize(width: 100, height: 100)
private var xoAssociationKey: UInt8 = 0
extension UIButton {
var isIncreasedHitAreaEnabled: Bool {
get {
return (objc_getAssociatedObject(self, &xoAssociationKey) != nil)
}
set(newValue) {
objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
if isIncreasedHitAreaEnabled {
// increase the hit frame to be at least as big as `minimumHitArea`
let buttonSize = self.bounds.size
let widthToAdd = max(minimumHitArea.width - buttonSize.width, 0)
let heightToAdd = max(minimumHitArea.height - buttonSize.height, 0)
let largerFrame = self.bounds.insetBy(dx: -widthToAdd / 2, dy: -heightToAdd / 2)
// perform hit test on larger frame
return (largerFrame.contains(point)) ? self : nil
}
return self
}
}