Creating Info Button and Increasing Touch Area

The info button offers a familiar symbol for prompting the user to request more information. This is a common button used for “About” screens. The iPhone SDK includes a specific button type for creating an info button, in both dark and light versions, which allows the button to appear over most backgrounds.

Creating an info button is as simple as shown below:

- (void)buttonPressed:(UIButton *)button
{
...
}
 
- (void)someMethod
{
  UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
  infoButton.frame = CGRectMake(10, 10, 16, 16);
  infoButton.backgroundColor = [UIColor clearColor];
  [infoButton addTarget:self action:@selector(buttonPressed:) 
           forControlEvents:UIControlEventTouchUpInside];    
  [self.view addSubview:infoButton];
}

The image button will look as shown below. Notice the @selector, which specifies which method will be called when someone touches the info button.

Speaking of touching the info button, one change I recommend is to increase the frame size of info button so there is a larger area on the screen that is receptive to a touch. To keep the info button defined above in the same location, and at the same time define a larger touch area, you can change the frame as shown in the code below, which will increase the touch area 40 pixels in both the x and y directions.

infoButton.frame = CGRectMake(-10, -10, 56, 56);

Notice how we need to change the x and y locations (-10, -10) in order to keep the image in the same location on the screen, once we increase it’s size.

Another approach, which I prefer given it’s readability and clear intention to change the frame, is to setup the original frame, then update the x and y coordinates as well as the width and height.

infoButton.frame = CGRectMake(10, 10, 16, 16);
...
// Change the existing touch area by 40 pixels in each direction
// Move the x/y starting coordinates so the button remains in the same location
CGRect rect = CGRectMake(
     infoButton.frame.origin.x - 20,
     infoButton.frame.origin.y - 20,
     infoButton.frame.size.width + 40,
     infoButton.frame.size.height + 40);
[infoButton setFrame:rect];

17 Comments

  1. Or to do it without figuring out the numbers yourself,

    // First set the coords to whatever
    infoButton.frame = CGRectMake(10, 10, 16, 16);

    // Then use CGRectInset
    infoButton.frame = CGRectMake(infoButton.frame,-40,-40);
    // And move it properly
    infoButton.frame = CGRectOffset(infoButton.frame,-20,-20);

  2. I’ve found it helpful to create a helper class (I call it CGSupport, maybe not the best name) with static functions to do common manipulations of CGRect and CGPoint structures. Things like:

    + (CGRect) moveRect: (CGRect) originalRect deltaX: (int) deltaX deltaY: (int) deltaY;
    + (CGRect) moveRect: (CGRect) originalRect deltaX: (int) deltaX;
    + (CGRect) moveRect: (CGRect) originalRect deltaY: (int) deltaY;
    + (CGRect) scaleRect: (CGRect) originalRect factorX: (float) factorX factorY: (float) factorY anchor: (enum RectAnchor) anchor; // enum RectAnchor { RectAnchor_Center, RectAnchor_TopLeft, etc. }

    With scaleRect, you can just call:

    CGRect rect = [CGSupport scaleRect: infoButton.frame factorX: 40.0/16.0 factorY: 40.0/16.0 anchor: RectAnchor_Center];

  3. I’ve given the code from Seventoes a try and it’s even easier than the two lines mentioned. To increase the size of the touch area by 40 pixels in each direction and keep the button in the same location, give this a go:

    infoButton.frame = CGRectInset(infoButton.frame, -20, -20);

  4. Well, that figures. I missed out on all those helper functions in CGGeometry. That’s what happens when you are so busy cranking out code that you forget to do basic research. So thank you, John, for the tip.
    (Incidentally, the post from seventoes was still in moderation when I posted, so I didn’t see it.)

  5. Michelle, I like idea of your helper class, I can see where the scaleRect with enum would be good to have around.

  6. Changing the frame for the info button… so simple and yet so effective.

    I have struggling to make my info buttons more ‘responsive’, and I ended up using photoshop to create a ‘bigger info button’ image (actually the info button inside a big black square…) So much easier to simply extend the frame.
    Thanks a lot John. It really helps.

  7. What if the button, that i named btnAbout, is created in Interface Builder?
    Where do i write the code
    btnAbout.frame = CGRectInset(btnAbout.frame, -20, -20);
    ?

    Thanks and sorry if it’s a silly question, but i’m a newbie :-)

  8. @Luca: just put it in the viewDidLoad function in your ViewController class. And no, it’s not a silly question. We’ve all been there at some point or another. Good luck.

  9. Hi thanks for the answer.
    It didn’t work for the button created in the interface builder.
    It seems that the frame values for the info button are somehow locked if the button is created in the IB.
    Btw creating the button programmatically works smoothly.
    Thanks a lot for your code. It helped me a lot.
    Luca

  10. @Luca: make sure your button is correctly bound to a your variable ‘btnAbout’ in Interface Builder. If you forgot to bind it, you will basically send the setFrame message to nil and you won’t get a runtime error (it’s either a good or bad feature of obj c, depending on how you look at it…)

    I am saying this because I used IB to create my interface, added the code at the beginning of viewDidLoad and it works like a charm…

  11. thanks a lot for your help guys !!

    How to fade out info button after some seconds ???

    any example code plzz..

  12. @Dorald
    How to fade out info button after some seconds ???

    [button setAlpha: 1.0f];

    [UIView beginAnimations: nil context:NULL];
    // time delay in seconds to start
    [UIView setAnimationDelay:2.0f];
    // time in seconds for the fading, 0.25sec is the default apple time for small animations
    [UIView setAnimationDuration:0.25f];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [button setAlpha: 0.0f];
    [UIView commitAnimations];

  13. How do I detect what color is under the InfoButton… so I can change the button
    from DARK to LIGHT?

    I set my view’s color… but how do I tell if it’s “kind of light” or “kind of dark”?

    Besides… I can’t change the info-button from light to dark anyway. (read only)

    Ugh.

    Shouldn’t Apple have some kind of a simple “cmdButton.doThisExtremelyCommonThingForMe = TRUE” statement?

    InfoButtons are useless if you can’t even see them.

    • Paula, I’m not sure I entirely understand what you are trying to do…however, you can look at the buttonType property for a UIButton and determine if it’s UIButtonTypeInfoLight or UIButtonTypeInfoDark.

    • Hey Paula,

      I wanted to do the same thing, to ensure visibility of the info button.
      So I made 2 UIButtons with the same position, linked to the same IBAction. (Yah, you guessed right: “btnInfoDark” of type ‘Info Dark’, and “btnInfoLight” of type ‘Info Light’)

      When I had a dark background I hid btnInfoDark with .btnInfoDark.hidden = TRUE; and did the same for the light background .btnInfoLight.hidden = TRUE;
      I was setting the view background with self.backgroundColor = [UIColor ], so I knew the background color. But you could also get the background of the object/view behind by checking its .background property.

      Finding out when the color is somewhat dark or light remains another matter. Maybe this thread can help you calculate the darkness of a given color: http://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color.

      PS
      cmdButton.doThisExtremelyCommonThingForMeToo = TRUE

  14. Please can anyone tell me how to increase the size of info button???Is it possible to do..Reply..
    Thanks

Comments are closed.