[英]how can I expand the hit area of a specific UIButton in Swift?
In my application I have a UIButton
that is quite small, so I thought about increasing the hit area of it. 在我的应用程序中,我有一个很小的UIButton
,所以我考虑增加它的点击区域。
I found an extension for that: 我找到了一个扩展名:
fileprivate let minimumHitArea = CGSize(width: 100, height: 100)
extension UIButton {
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
// increase the hit frame to be at least as big as `minimumHitArea`
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
}
}
but when I use it, every button in my app has a bigger hit area. 但是当我使用它时,我应用程序中的每个按钮都有较大的点击区域。 I want to increase it to only one specialButton
- how can I do it? 我想将其增加到仅一个specialButton
我该怎么做?
You can add a computed property
to your extension which you can set in your controller if you want to enable the hit area like this: 您可以在扩展程序中添加一个computed property
,如果要启用点击区域,可以在控制器中进行设置:
fileprivate let minimumHitArea = CGSize(width: 100, height: 100)
extension UIButton {
var isIncreasedHitAreaEnabled: Bool {
get {
// default value is false, so you can easily handle from outside when to enable the increased hit area of your specific button
return false
}
set {
}
}
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
// only if it's true the hit area can be increased
if isIncreasedHitAreaEnabled {
// increase the hit frame to be at least as big as `minimumHitArea`
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
}
return self
}
}
And then in your view controller just set isIncreasedHitAreaEnabled
to true
if you want to increase it for a specific button (eg in your viewDidLoad
): 然后,如果要为特定按钮(例如,在viewDidLoad
)增加它,则在视图控制器中只需将isIncreasedHitAreaEnabled
设置为true
即可:
override func viewDidLoad() {
super.viewDidLoad()
specialButton.isIncreasedHitAreaEnabled = true
}
Update: 更新:
First of all the method which you use doesn't work like expected. 首先,您使用的方法无法正常工作。 And also my approach with the computed property
did not work like I thought. 而且,我对computed property
也不像我想的那样有效。 So even if the method does not work like expected, I just want to update my approach with the computed property
. 因此,即使该方法无法按预期工作,我也只想使用computed property
来更新我的方法。 So to set the property from outside, you can use Associated Objects . 因此,要从外部设置属性,可以使用关联对象 。 Also have look here . 也可以看看这里 。 With this solution now it would be possible to handle the Bool
property isIncreasedHitAreaEnabled
from your controller: 现在,通过此解决方案,可以从您的控制器处理Bool
属性isIncreasedHitAreaEnabled
:
fileprivate let minimumHitArea = CGSize(width: 100, height: 100)
private var xoAssociationKey: UInt8 = 0
extension UIButton {
var isIncreasedHitAreaEnabled: Bool {
get {
return (objc_getAssociatedObject(self, &xoAssociationKey) != nil)
}
set(newValue) {
objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// if the button is hidden/disabled/transparent it can't be hit
if self.isHidden || !self.isUserInteractionEnabled || self.alpha < 0.01 { return nil }
if isIncreasedHitAreaEnabled {
// increase the hit frame to be at least as big as `minimumHitArea`
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
}
return self
}
}
Don't expand the hit area; 不要扩大打击范围; shrink the drawing area. 缩小绘图区域。 Make the button a subclass of UIButton, and in that subclass, implement rect
methods, along these lines: 使按钮成为UIButton的子类,并在该子类中实现rect
方法,方法如下:
class MyButton : UIButton {
override func contentRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: 30, dy: 30)
}
override func backgroundRect(forBounds bounds: CGRect) -> CGRect {
return bounds.insetBy(dx: 30, dy: 30)
}
}
Now the button is tappable 30 points outside its visible background. 现在,该按钮在其可见背景之外可以点击30点。
Create a Custom UIButton Class and override pointInside:(CGPoint)point method like below. 创建一个自定义UIButton类,并覆盖pointInside:(CGPoint)point方法,如下所示。 Then set these properties value from viewController. 然后从viewController设置这些属性值。
#import <UIKit/UIKit.h>
@interface CustomButton : UIButton
@property (nonatomic) CGFloat leftArea;
@property (nonatomic) CGFloat rightArea;
@property (nonatomic) CGFloat topArea;
@property (nonatomic) CGFloat bottomArea;
@end
#import "CustomButton.h
@implementation CustomButton
-(BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGRect newArea = CGRectMake(self.bounds.origin.x - _leftArea, self.bounds.origin.y - _topArea, self.bounds.size.width + _leftArea + _rightArea, self.bounds.size.height + _bottomArea + _topArea);
return CGRectContainsPoint(newArea, point);
}
@end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.