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




uibutton type (5)

以下是接受答案的更正版本。 我们使用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);
}

https://code.i-harness.com

我已经设置了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;
}

一个更干净的方法是重写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
    }
}

我为这个目的建了一个图书馆

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

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

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

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

https://github.com/kgaidis/KGHitTestingViews

@interface KGHitTestingButton : UIButton <KGHitTesting>

@property (nonatomic) CGFloat minimumHitTestHeight; 
@property (nonatomic) CGFloat minimumHitTestWidth;

@end

你也可以在不写任何代码的情况下继承和使用Interface Builder:





uibutton