28

I have made the UIButton programmatically

togglebutton = [UIButton buttonWithType:UIButtonTypeCustom];
togglebutton.frame = CGRectMake(42, 15, 80, 21);
[togglebutton addTarget:self action:@selector(toggleview)   
forControlEvents:UIControlEventTouchUpInside];
[togglebutton setImage:[UIImage imageNamed:@"squ.png"] forState:UIControlStateNormal];
[buttonView addSubview:togglebutton];

enter image description here

It is looked as the right button in above image. Now the requirement is that the selection area of this button should be more than then the uibutton image. So that the user will be able to click the button easily by touching on near by area of particular button.

[togglebutton setImageEdgeInsets: UIEdgeInsetsMake( 0, -30, 0, -25)];

I tried to set the image inset but it making the image irregular. Please look upon this issue.

icodebuster
  • 8,890
  • 7
  • 62
  • 65
Minkle Garg
  • 1,397
  • 3
  • 13
  • 27
  • How did you choose those insets and what other values did you try? – Wain Jun 22 '13 at 09:18
  • Look at this and try changing the view mode of the button image, then it should work with the insets and the image should stay the same - http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html – Dominik Hadl Jun 22 '13 at 09:22
  • @Wain I set the image inset with the difference of button and image size – Minkle Garg Jun 22 '13 at 09:26
  • Possible duplicate of [UIButton: Making the hit area larger than the default hit area](http://stackoverflow.com/questions/808503/uibutton-making-the-hit-area-larger-than-the-default-hit-area) – kgaidis Oct 29 '16 at 19:20
  • I recommend this answer [uibutton-making-the-hit-area-larger-than-the-default-hit-area](http://stackoverflow.com/questions/808503/uibutton-making-the-hit-area-larger-than-the-default-hit-area). Maybe it can help most of us – guozqzzu Dec 15 '16 at 02:37
  • Maybe help, my solution on Swift 3: https://stackoverflow.com/a/45436719/6013170 – Janserik Aug 01 '17 at 11:37

9 Answers9

47

You can achieve this by setting the button's contentEdgeInsets, for example:

toggleButton.contentEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0); //set as you require 
cmyr
  • 2,235
  • 21
  • 30
Nitin Gohel
  • 49,482
  • 17
  • 105
  • 144
  • 6
    According to the property declaration, you would need negative values for the inset to increase the selection area. Use this property to resize and reposition the effective drawing rectangle for the button content. The content comprises the button image and button title. You can specify a different value for each of the four insets (top, left, bottom, right). A positive value shrinks, or insets, that edge—moving it closer to the center of the button. A negative value expands, or outsets, that edge. – kevinl Sep 01 '15 at 19:28
  • You can also set this directly in the storyboard from the xcode gui. To do so select the button you want and choose the "identity inspector", then add a "User Define Runtime Attribute" named "contentEdigeInsets" of type "Rect". This is sometime more convenient than doing it in code. – Amos Joshua Sep 19 '16 at 13:34
  • 1
    FYI: Positive values do increase the tappable area of the button. – duncanc4 Jan 27 '17 at 14:06
  • To add on, I just increased button size and then set UIEdgeInsets to positive numbers of how much increased. – green0range Jan 24 '18 at 23:29
18

For Swift

You can override func 'pointInside' of UIView class to expand clickable area.

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    // padding : local variable of your custom UIView, CGFloat
    // you can change clickable area dynamically by setting this value.

    let newBound = CGRect(
        x: self.bounds.origin.x - padding,
        y: self.bounds.origin.y - padding,
        width: self.bounds.width + 2 * padding,
        height: self.bounds.height + 2 * padding
    )
    return CGRectContainsPoint(newBound, point)
}

Use like this,

class MyButton: UIButton {
    var padding = CGFloat(0) // default value

    //func pointInside at here!!
}

When you init your button, set your custom padding.

func initButton() {
    let button = MyButton(frame: CGRect(x: 100, y: 100, width: 30, height: 30))
    button.padding = 10 // any value you want
    view.addSubview(button)
}

then your button is in frame (x: 100, y:100, width: 30, height: 30)

and your button's clickable area might be in the frame with (x: 90, y: 90, width: 50, height: 50)

** Be sure to check overlapping with any other view, because its clickable area is larger than it looks.

Update for Swift 3

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
    let padding = CGFloat(10)
    let extendedBounds = bounds.insetBy(dx: -padding, dy: -padding)
    return extendedBounds.contains(point)
}
Daniel Saidi
  • 6,079
  • 4
  • 27
  • 29
Mark
  • 493
  • 5
  • 10
3

Try using contentEdgeInsets property of the UIButton.

Adithya
  • 4,545
  • 3
  • 25
  • 28
3

in xcode 9 you can do the following:

xcode 9 screenshot

that means you have to compensate the image offset and content offset to ensure a centered image positioning.

olidem
  • 1,961
  • 2
  • 20
  • 45
2

The Below code solves my problem.This is very basic way, Try this :

    button.contentEdgeInsets = UIEdgeInsetsMake(15, 20, 10, 10);  //Change x,y,width,height as per your requirement.
Suraj Sonawane
  • 2,044
  • 1
  • 14
  • 24
1

For Objective C

Create this custom UIButton Class and assign it into your button. Then set these properties values from viewController.

//This is .h file
     #import <UIKit/UIKit.h>
        @interface CustomButton : UIButton
        @property (nonatomic) CGFloat leftArea;
        @property (nonatomic) CGFloat rightArea;
        @property (nonatomic) CGFloat topArea;
        @property (nonatomic) CGFloat bottomArea;
        @end



        //.m file is following
        #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
0

In my case, my button image is small and I want to increase button area while not increasing uibutton image size because it will look blurred. So I increased button frame and then set button image setImageEdgeInsets. Positive values for edgeInsets will shrink and negative values will expand.

self.menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.menuButton addTarget:self
                  action:@selector(onSideBarButtonTapped:)
        forControlEvents:UIControlEventTouchDown];
[self.menuButton setImage:[UIImage imageNamed:@"menu"]
                         forState:UIControlStateNormal];
self.menuButton.frame = CGRectMake(10, 3, 40, 40);

Now I am going to shrink image size so that button will not look blurred.

[self.menuButton setImageEdgeInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
Mel
  • 5,837
  • 10
  • 37
  • 42
i.AsifNoor
  • 587
  • 5
  • 14
-2

I would create a UIView around that button so that you can set the size to whatever you want. Then I'd set the UIView's background color to the clear color (do not set opacity to 0 or the gesture won't be recognized)

Then add a UIGestureRecognizer to the uiview to handle the same IBAction

Of course, many people will encourage/prefer the use of the edgeInsets

kevinl
  • 4,194
  • 6
  • 37
  • 55
-2

Here is an example of increasing touchable area of custom UIButton:

UIImage *ButtonImage=[UIImage imageNamed:@"myimage.png"];
UIButton *myButton=[UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame=CGRectMake(10, 25, ButtonImage.size.width/2+10, ButtonImage.size.height/2+10);
[myButton setImage:ButtonImage forState:UIControlStateNormal];
myButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5);
[myButton addTarget:self action:@selector(crossButtonClick:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:myButton];

Hope it would be helpful.

Santosh
  • 1,254
  • 2
  • 16
  • 31