12

I'm using few gesture recognizers on some views, but sometimes views are too small and it's hard to hit it. Using recognizers is necessary, so how can I enlarge hit area?

Tesseract
  • 342
  • 4
  • 12

3 Answers3

24

If you are doing this for a custom UIView, you should be able to override the hitTest:withEvent: method:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    CGRect frame = CGRectInset(self.bounds, -20, -20);

    return CGRectContainsPoint(frame, point) ? self : nil;
}

The above code will add a 20 point border around the view. Tapping anywhere in that area (or on the view itself) will indicate a hit.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • 2
    I think it is better to override pointInside because hitTest calls pointInside: recursively on subviews. – pronebird Nov 25 '15 at 12:35
6

Swift version of @rmaddy answer:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    let frame = self.bounds.insetBy(dx: -20, dy: -20);
    return frame.contains(point) ? self : nil;
}
3

If you're using a UIImageView as a button, you can use the following extension (Swift 3.0):

extension UIImageView {
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }

    let minimumHitArea = CGSize(width: 50, height: 50)
    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
}
}

Similar to the UIButton extension here

Community
  • 1
  • 1
Sir Codesalot
  • 7,045
  • 2
  • 50
  • 56