Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何在不挤压UIButton的情况下扩展其hitTest区域';背景图像是什么?_Iphone_Objective C_Ios_Uibutton - Fatal编程技术网

Iphone 如何在不挤压UIButton的情况下扩展其hitTest区域';背景图像是什么?

Iphone 如何在不挤压UIButton的情况下扩展其hitTest区域';背景图像是什么?,iphone,objective-c,ios,uibutton,Iphone,Objective C,Ios,Uibutton,我已经设置了ui按钮的背景图像,并在其上添加了一个标题(我使用了setBackgroundImage方法而不是setImage)。现在我想扩展UIButton的点击测试区域,而不挤压它的背景图像 我如何才能做到这一点?您可以扩展UIButton并覆盖UIView的hitTest方法: - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { int expandMargin = 20; CGRect exten

我已经设置了
ui按钮的背景图像,并在其上添加了一个标题(我使用了
setBackgroundImage
方法而不是
setImage
)。现在我想扩展
UIButton
的点击测试区域,而不挤压它的背景图像


我如何才能做到这一点?

您可以扩展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

以下是一个快速版本:

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

此版本允许您为所有UIButton定义最小点击大小。关键的是,它还可以处理隐藏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
或者您可以将UIView或UIButton子类化,并设置
minimumHitTestWidth
和/或
minimumHitTestHeight
。然后,按钮点击测试区域将由这2个值表示

与其他解决方案一样,它使用
-(BOOL)pointInside:(CGPoint)pointwithevent:(UIEvent*)event
方法。当iOS执行命中测试时调用该方法。这篇博客文章很好地描述了iOS命中测试的工作原理

@接口KGHitTestingButton:UIButton
@属性(非原子)CGFloat最小HitTestHeight;
@属性(非原子)CGFloat最小HitTestWidth;
@结束
您也可以只创建子类并使用Interface Builder,而无需编写任何代码:

这是不正确的。
位于本地坐标系中,如果
视图
原点
不等于
CGPointZero
,则使用
代替
边界
会导致问题。CGRectInset将比疯狂的cgrectmake更好不要忘记检查视图是否可见并且有窗口,否则你可能会得到有趣的结果…@steipet希望你的评论早点发布。。。结果不是那么有趣!
@interface KGHitTestingButton : UIButton <KGHitTesting>

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

@end