How to expand hitTest UIButton area without extruding its background image?

I set the background image of UIButton and put the title in it (I used the setBackgroundImage not setImage ). Now I want to expand the hitTest UIButton without extruding its background image.

How can i do this?

+4
source share
5 answers

Well, you can extend UIButton and override the UIView hitTest method:

 - (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; } 
+1
source

Here the version of the accepted answer is fixed. We use bounds instead of frame and CGRectInset instead of CGRectMake . Cleaner and more reliable.

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

A cleaner way to do this is to override pointInside.

Here is the Swift version:

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

This version allows you to define the minimum beat size for all UIButtons. Actually, it also handles the case where the UIButtons are hidden, that many responses are ignored.

 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 } } 
0
source

I made a library for this very purpose.

You can select a category, no subclasses are required :

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

Or you can subclass UIView or UIButton and set minimumHitTestWidth and / or minimumHitTestHeight . Then your test area will be represented by these two values.

Like other solutions, it uses the - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event . The method is called when iOS performs impact testing. This blog post has a good description of how iOS hit-testing works.

https://github.com/kgaidis/KGHitTestingViews

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

You can also just subclass and use the interface builder without writing code: enter image description here

0
source

Source: https://habr.com/ru/post/1432686/


All Articles