如何扩展UIButton的hitTest区域而不挤压它的背景图像?

我已经设置了UIButton的背景图像,并把标题(我用setBackgroundImage方法不setImage )。 现在我想展开一个UIButton的hitTest区域而不挤出它的背景图像。

我怎样才能做到这一点?

那么,你可以扩展UIButton并重写UIView的hitTest方法:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { int expandMargin = 20; CGRect extendedFrame = CGRectMake(0 - expandMargin , 0 - expandMargin , self.bounds.size.width + (expandMargin * 2) , self.bounds.size.height + (expandMargin * 2)); return (CGRectContainsPoint(extendedFrame , point) == 1) ? self : nil; } 

以下是接受答案的更正版本。 我们使用bounds而不是frameCGRectInset而不是CGRectMake 。 更清洁,更可靠。

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return CGRectContainsPoint([self expandedBounds], point) ? self : nil; } - (CGRect)expandedBounds { return CGRectInset(self.bounds, -20, -20); } 

一个更干净的方法是重写pointInside。

这是一个Swift版本:

 override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { let expandedBounds = CGRectInset(self.bounds, -15, -15) return CGRectContainsPoint(expandedBounds, point) } 

这个版本可以让你为所有的UIButtons定义一个最小的命中大小。 至关重要的是,它也处理的情况下,UIButtons隐藏,许多答案忽视。

 extension UIButton { public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { // Ignore if button hidden if self.hidden { return nil } // If here, button visible so expand hit area let hitSize = CGFloat(56.0) let buttonSize = self.frame.size let widthToAdd = (hitSize - buttonSize.width > 0) ? hitSize - buttonSize.width : 0 let heightToAdd = (hitSize - buttonSize.height > 0) ? hitSize - buttonSize.height : 0 let largerFrame = CGRect(x: 0-(widthToAdd/2), y: 0-(heightToAdd/2), width: buttonSize.width+widthToAdd, height: buttonSize.height+heightToAdd) return (CGRectContainsPoint(largerFrame, point)) ? self : nil } } 

我为这个目的build了一个图书馆 。

您可以select使用一个类别, 不需要子类

 @interface UIView (KGHitTesting) - (void)setMinimumHitTestWidth:(CGFloat)width height:(CGFloat)height; @end 

或者你可以minimumHitTestWidth你的UIView或UIButton并设置minimumHitTestWidth和/或minimumHitTestHeight 。 您的button命中testing区域将由这两个值表示。

就像其他解决scheme一样,它使用- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event方法。 该方法在iOS执行命中testing时被调用。 这篇博文对iOS命中testing如何工作有很好的描述。

https://github.com/kgaidis/KGHitTestingViews

 @interface KGHitTestingButton : UIButton <KGHitTesting> @property (nonatomic) CGFloat minimumHitTestHeight; @property (nonatomic) CGFloat minimumHitTestWidth; @end 

你也可以在不写任何代码的情况下inheritance和使用Interface Builder: 在这里输入图像说明