Resources : Blog

iPhone UIButton tutorial: Radio Buttons

By Pritam Barhate in iPhone - iPad

May 4, 2010

< All >

Radio buttons is a set of buttons out of which only one can be set at a time. For example: Selecting the time format out of 12-hr and 24-hr in a clock application.They are often required in iPhone UIs. Unfortunately, they are not included in the iPhone sdk. In this tutorial, we will learn how to create custom radio buttons.

Step 1: Create a window based application in Xcode and name it “MIRadioButtonGroup”.

Step 2: Create new “MIRadioButtonGroup.h” and “MIRadioButtonGroup.m” files which extend from UIView.
(Classes >> Add >> New File >> Objective C Class. Select UIView in the “subclass of” list.)

Step 3: Create a new group in the Classes folder and name it “MIRadioButtonGroup”. Drag the “MIRadioButtonGroup .h” and “MIRadioButtonGroup .m” files into the group.Now, add the images “radio-on.png” and “radio-off.png” to the group.

Step 4: Open the “MIRadioButtonGroup.h” file and make the following changes in it.

[objc highlight="2,5,7,8,9,10,11,12"]
@interface MIRadioButtonGroup : UIView {
NSMutableArray *radioButtons;
}

@property (nonatomic,retain) NSMutableArray *radioButtons;

- (id)initWithFrame:(CGRect)frame andOptions:(NSArray *)options
andColumns:(int)columns;
-(IBAction) radioButtonClicked:(UIButton *) sender;
-(void) removeButtonAtIndex:(int)index;
-(void) setSelected:(int) index;
-(void)clearAll;
@end
[/objc]

Here, we have declared a mutable array “radioButtons” which will hold all the buttons that we add to the radio button group.

The methods declared are:
initWithFrame – It is a constructor used to initialize the group. It takes the frame for the entire group,an array holding the titles of the buttons and the number of columns in which the buttons are to be arranged as input parameters.

radioButtonClicked – This method is used to set the button which is clicked.

removeButtonAtIndex – This method is used to remove a radio button at a particular index from the group.

setSelected – This method is used to set the button at the specified index.

clearAll – This method clears all the buttons including the currently set button.

Step 5: Open the “MIRadioButtonGroup.m” file and put the following code in it.
[objc highlight="4,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,83,87,88,89,90,91,92,93,94,95,96,97,99,100,101,103,104,105,106,107,108,109,110,111,112,114,115,116,117,118,119,120"]
#import &quot;MIRadioButtonGroup.h&quot;

@implementation MIRadioButtonGroup
@synthesize radioButtons;

- (id)initWithFrame:(CGRect)frame andOptions:(NSArray *)options
andColumns:(int)columns{

NSMutableArray *arrTemp =[[NSMutableArray alloc]init];
self.radioButtons =arrTemp;
[arrTemp release];
if (self = [super initWithFrame:frame]) {
// Initialization code
int framex =0;
framex= frame.size.width/columns;
int framey = 0;
framey =frame.size.height/([options count]/(columns));
int rem =[options count]%columns;
if(rem !=0){
framey =frame.size.height/(([options count]
/columns)+1);
}
int k = 0;
for(int i=0;i&amp;lt;([options count]/columns);i++){
for(int j=0;j&lt;columns;j++){

int x = framex*0.25;
int y = framey*0.25;
UIButton *btTemp = [[UIButton alloc]
initWithFrame:CGRectMake(framex*j+x, framey*i+y,
framex/2+x, framey/2+y)];
[btTemp addTarget:self action:
@selector(radioButtonClicked:)
forControlEvents:UIControlEventTouchUpInside];
btTemp.contentHorizontalAlignment =
UIControlContentHorizontalAlignmentLeft;
[btTemp setImage:[UIImage imageNamed:
@&quot;radio-off.png&quot;] forState:UIControlStateNormal];
[btTemp setTitleColor:[UIColor blackColor]
forState:UIControlStateNormal];
btTemp.titleLabel.font =[UIFont systemFontOfSize:14.f];
[btTemp setTitle:[options objectAtIndex:k]
forState:UIControlStateNormal];
[self.radioButtons addObject:btTemp];
[self addSubview:btTemp];
[btTemp release];
k++;

}
}

for(int j=0;j&lt;rem;j++){

int x = framex*0.25;
int y = framey*0.25;
UIButton *btTemp = [[UIButton alloc]
initWithFrame:CGRectMake(framex*j+x,
framey* ([options count]/columns),
framex/2+x,framey/2+y)];
[btTemp addTarget:self action:@selector(radioButtonClicked:)
forControlEvents:UIControlEventTouchUpInside];
btTemp.contentHorizontalAlignment =
UIControlContentHorizontalAlignmentLeft;
[btTemp setImage:[UIImage imageNamed:@&quot;radio-off.png&quot;]
forState:UIControlStateNormal];
[btTemp setTitleColor:[UIColor blackColor]
forState:UIControlStateNormal];
btTemp.titleLabel.font =[UIFont systemFontOfSize:14.f];
[btTemp setTitle:[options objectAtIndex:k]
forState:UIControlStateNormal];
[self.radioButtons addObject:btTemp];
[self addSubview:btTemp];
[btTemp release];
k++;

}

}
return self;
}

- (void)dealloc {
[radioButtons release];
[super dealloc];
}

-(IBAction) radioButtonClicked:(UIButton *) sender{

for(int i=0;i&amp;lt;[self.radioButtons count];i++){
[[self.radioButtons objectAtIndex:i] setImage:[UIImage
imageNamed:@&quot;radio-off.png&quot;]
forState:UIControlStateNormal];
}
[sender setImage:[UIImage imageNamed:@&quot;radio-on.png&quot;]
forState:UIControlStateNormal];

}

-(void) removeButtonAtIndex:(int)index{
[[self.radioButtons objectAtIndex:index] removeFromSuperview];
}

-(void) setSelected:(int) index{
for(int i=0;i&amp;lt;[self.radioButtons count];i++){
[[self.radioButtons objectAtIndex:i] setImage:[UIImage
imageNamed:@&quot;radio-off.png&quot;] forState:UIControlStateNormal];

}
[[self.radioButtons objectAtIndex:index] setImage:[UIImage
imageNamed:@&quot;radio-on.png&quot;] forState:UIControlStateNormal];

}

-(void)clearAll{
for(int i=0;i&amp;lt;[self.radioButtons count];i++){
[[self.radioButtons objectAtIndex:i] setImage:[UIImage
imageNamed:@&quot;radio-off.png&quot;]
forState:UIControlStateNormal];
}
}

@end
[/objc]
initWithFrame – In this method, we first divide the frame into n number of boxes with width framex and height framey, where n =([options count]/columns)*columns. Then we check to see if there is any remainder for ([options count]/columns). The reason for this will be explained later.
In the proceeding nested “for” loops, we set the frames of the buttons so that each button occupies 50% space of each of the n boxes. After that we link the button programmatically to the “radioButtonClicked” method. We set the alignment of the content(radio button image and title) to left. Then we set the image for the button, configure its font color and font size and set its title.

This code works fine when the number of buttons is perfectly divisible by columns, but when it is not, the remaining buttons are not printed.
Now, the remainder comes in picture. What we do is, if there is a non-zero remainder, we add 1 to the divisor in framey equation,so that there is space for an extra row in the frame. In the next “for” loop, we insert that extra row and hence, cover the missing buttons.

radioButtonClicked – Here, we first clear all the buttons in the “radioButtons” array by setting their images to “radio-off.png”. Then, we set only the sender button by setting its image to “radio-off”.

removeButtonAtIndex – In this method, we remove the button at the specified index with the “removeFromSuperview” method.

setSelected – This method is similar to the “radioButtonClicked” method. The difference is we set the button at the specified index in the “radioButtons” array.

clearAll – In this method, we clear all the radio buttons by setting the images of the buttons in “radioButton” to “radio-off.png”.

Step 6: Now that we have created the “MIRadioButtonGroup” files, put the following code in the “MIRadioButtonGroupAppDelegate.m” file so that we can test them.
[objc highlight="2,10,11,12,13,14,15,16,17,18,19"]
#import &quot;MIRadioButtonGroupAppDelegate.h&quot;
#import &quot;MIRadioButtonGroup.h&quot;

@implementation MIRadioButtonGroupAppDelegate
@synthesize window;

- (void)applicationDidFinishLaunching:(UIApplication *)application {

// Override point for customization after application launch
NSArray *options =[[NSArray alloc]
initWithObjects:@&quot;1&quot;,@&quot;2&quot;,@&quot;3&quot;,@&quot;4&quot;,@&quot;5&quot;,@&quot;6&quot;,nil];
MIRadioButtonGroup *group =[[MIRadioButtonGroup alloc]
initWithFrame:CGRectMake(0, 20, 320, 75)
andOptions:options andColumns:4];
[options release];
[window addSubview:group];
//[group setSelected:1];
//[group clearAll];
//[group removeButtonAtIndex:2];
[window makeKeyAndVisible];
}

- (void)dealloc {
[window release];
[super dealloc];
}

@end
[/objc]
Step 7: Save, build and run the project. The output will be Output1. Now uncomment the commented lines one by one and observe the output. It will be Output 2, Output 3 and Output 1 respectively.

You can download the source code here.

  • Tatiana

    nice

  • Steve Kowalski

    Excellent! I did notice that when columns is set to 1 or 2 that the button images are not drawn properly