如何扩展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
而不是frame
和CGRectInset
而不是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: