iPhone Tutorial - Creating Basic Buttons

Skill

iPhone Tutorial - Creating Basic Buttons

Posted in:

In our previous introductory tutorial on iPhone development, a question was asked about how to create a button and listen for its UIControlEventTouchUpInside event. I didn't want to put everything that was required into the comments of that post, so I created this tutorial as an answer. Much like the last tutorial, I'm still avoiding Interface Builder and am going to build the button using nothing but code.

I'm going to use the code created from the last tutorial as a starting point, so I would recommend checking that one out if you're new to iPhone development. Basically what we're starting with is a new Window-Based application with one UIViewController subclass. We've implement the loadView function, which basically gives us total control over populating the view controller with our views. Here's the code that's needed before we can begin with our button.

// Implement loadView to create a view hierarchy programmatically,
// without using a nib.
- (void)loadView {
       
  //allocate the view
  self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
       
  //set the view's background color
  self.view.backgroundColor = [UIColor whiteColor];
}

All we're doing here is creating the UIViewController's view object, setting its size to the entire screen, and making its background white. This is slightly different from the last tutorial since I no longer have to hardcode the size of the view. The UIScreen class has a class method, mainScreen, which we can use to get the screen of the device. We can then ask that object for its applicationFrame, which will be the total size of the iPhone's display.

All right, now let's get the basic stuff out of the way. Here's the code required to create the button and give it some text.

// Implement loadView to create a view hierarchy programmatically,
// without using a nib.
- (void)loadView {
       
  //allocate the view
  self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
       
  //set the view's background color
  self.view.backgroundColor = [UIColor whiteColor];
 
  //create the button
  UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
       
  //set the position of the button
  button.frame = CGRectMake(100, 170, 100, 30);
 
  //set the button's title
  [button setTitle:@"Click Me!" forState:UIControlStateNormal];
 
  //add the button to the view
  [self.view addSubview:button];
}

The first thing we need to do is create a button. The UIButton object has a class method called buttonWithType that automatically creates buttons with various types. We just want a regular old button so I passed in UIButtonTypeRoundedRect. Next up, we need to position and size the button, so I set the frame property to my specified bounds. A button's not much use without text, and setTitle is used to set it. You can specify a different title for each state, and if a title is not set for a specific state, it will use whatever was set for UIControlStateNormal. That's why it's the only state we're setting a title for. All that's left now is to add it as a subview to the UIViewController's view object. If you were to compile and run the code you'd see a button in the center of the screen.

iPhone Button Screenshot

A button doesn't do us a lot of good unless we know when it's been pressed. The next thing we need to add is a hook to listen for when the user clicks it.

// Implement loadView to create a view hierarchy programmatically,
// without using a nib.
- (void)loadView {
       
  //allocate the view
  self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
       
  //set the view's background color
  self.view.backgroundColor = [UIColor whiteColor];
 
  //create the button
  UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
       
  //set the position of the button
  button.frame = CGRectMake(100, 170, 100, 30);
 
  //set the button's title
  [button setTitle:@"Click Me!" forState:UIControlStateNormal];
 
  //listen for clicks
  [button addTarget:self action:@selector(buttonPressed)
   forControlEvents:UIControlEventTouchUpInside];
 
  //add the button to the view
  [self.view addSubview:button];
}

-(void)buttonPressed {
  NSLog(@"Button Pressed!");
}

We use the addTarget function to hook into the UIControlEventTouchUpInside event. Basically, what we're saying here is to send that event to self and call the function buttonPressed. The @selector directive returns what's essentially a function pointer in the Objective C world. Lastly, if we're telling the button to send a message to a class, we had better implement a method for that message, so all we do is simply log a message to the console. You can view the console by selecting Run / Console on XCode's menu.

That's it! Now you've got a button and you know when the user has clicked it. If you've got questions or comments feel free to leave them below or check out the forums.

huggie
06/07/2009 - 01:35

Nice tutorial, thanks. So how is everything hooked when one use the interface builder? Presumably the auto-generated codes goes to the xib files directly, but it seems like there is no explicit reference to the xib file in the delegate nor the controller code.

reply

Amir
11/05/2009 - 13:59

thanks for this great tutorial! one question though: why when I try to release the button in the end of the function it ruin the program? is what sense button different from label?

reply

Anonymous
11/17/2009 - 16:17

Amir, you don't need to release the button because you create it with the buttonWithType: method, which is a factory method and thus returns an autoreleased object. I suppose you create your UILabel using alloc, which is why you have to explicitly release it when you're done with it.

reply

Lite
11/19/2009 - 10:10

Very good for beginners. Got me started. Other documentation i found so far always got me stuck in details that were too advanced.

reply

natedog
01/03/2010 - 13:51

I had a problem in the - (void)loadView { part
Please Help.

reply

The Reddest
01/04/2010 - 12:07

Do you have any details?

reply

blindgoat
01/06/2010 - 01:29

Great starter tutorial. I don't know why there are so few people wanting to write programs without IB. Thank you :)

I'm trying to make a custom subView (I think) that is essentially this:

A square that is all clickable with a UILabel on top of it. I want to be able to place any picture I want on the background of the "button" square.

I want to be able to create as many instances of this as I want on screen and position them.

Do you have any hints for how I would go about doing this? You can email be at blindgoat AT g mail DOT COM

Thanks so much!
blindgoat

reply

hris2003
05/12/2010 - 15:57

Great tutorial. Thanks! :)

reply

TSquare
10/09/2010 - 20:17

Thanks this homeowork was really explicit and it helped me finish my homework. I am enrolled in an IOS programming class and the instructor refuses to let us use the interface builder. Thanks again. In a follow on post I will post my code to show how I used this post.

reply

Anonymous
02/22/2011 - 13:46

Thanks for helping an old C++ programmer get started with iPhone. Like you, I'd rather type code than click-and-drag.

reply

David
03/13/2011 - 10:40

Thanks, one question is there a way to pass parameters to the function that is linked to the button?

reply

Anonymous
03/14/2011 - 10:52

Hello,

I have an issue where my app is locked in landscape so when i add any buttons or labels the text for the buttons or labels are not landscape but instead still in portrait mode, so image that the text looks to be rising (vertical) out of the button instead of horizontal, since the button seems to be keeping its portrait property, is there any thing that can be done to make the buttons and labels also work in landscape mode?

reply

Anonymous
03/14/2011 - 19:35

So, you alloc-init your self.view... does this mean you need to release it somewhere?

reply

The Reddest
03/14/2011 - 20:02

The view controller will release the property as part of its own dealloc. We do not have to release the view property ourselves.

reply

Kiran PK
04/27/2011 - 00:02

I have practiced using Interface Builder..,
There.., what I used to do was to create a listner function which would return (IBAction)function:(id)sender and then used to link the same to the button in the interface builder..
And thats the advantage of having creating the UI from the code.., we can understand how exactly it all happens..
Great going.. Looking out for more tutorials..
Can you write about: storing some information in a sample database(like what we do in Android...SQLite) and then displaying them on the UI screen.
Thanks

reply

The Reddest
04/27/2011 - 08:57

Here's a tutorial we published a while ago. It should have what you're looking for.

reply

Anonymous
04/28/2011 - 06:43

heheheheh

reply

Maurizio
05/17/2011 - 07:35

I have add label control as previous example. I want write state button in label text, example, when I press button write "Button Pressed" in label text

- (void)loadView {
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor orangeColor];
//create Label
CGRect frameLabel = CGRectMake(100, 170, 100, 50);
UILabel *label = [[UILabel alloc] initWithFrame:frameLabel];
label.text = @"Button action";
[self.view addSubview:label];
[label release];

//create the button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(100, 270, 100, 30);
[button setTitle:@"Click me!" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];

}

-(void)buttonPressed {
//NSLog(@"Button Pressed");
label.text = @"Button Pressed";
}

but I receveid message "label undeclared", how resolve it?
thanks

reply

The Reddest
05/17/2011 - 08:56

label is declared in the scope of loadView. It cannot be accessed outside of that function. You need to declare the label using a class field (in the header file).

//header file (.h)
@interface YourClass {
  UILabel *label
}

//implementation file (.m)
-(void)loadView {
  label = [[UILabel alloc] initWithFrame:frameLabel];
}

Now label can be used in anywhere in the class.

reply

Maurizio
05/18/2011 - 03:07

ok, very simple
thank you for reply

reply

Ramil
05/20/2011 - 12:30

Hi, Redderst!
I tryed to use this example and I have a problem.
Application isn't calling the "buttonPressed" method. Log is empty.

reply

Ramil
05/21/2011 - 07:51

I've found a solution!

reply

Fabiano Libano
05/24/2011 - 18:09

Nice tutorial!

But i still have two questions:

- The button appears to me, but i want to associate it to an ibaction (without interface builder, of course) and make it starts the action when the user touch up inside the button. How can i do that???

-By default, the title of the button appears with the blue color, but i want to make it black. what code i need to use?

Thanks for help.

reply

Anonymous
06/28/2011 - 07:30

/nice tutorial ,thanks for the effort ,I want to know in a similar way whether we can create an array of buttons...
for(int i=0;i<3;i++)
{
............
}

thanks

reply

Daantjeeuh
09/16/2011 - 03:03

Works fine, but when I click the button nothing happens.. not in NSLog, nowhere.

reply

Tristan Hampe
12/14/2011 - 11:50

there is a great tutorial about the uibutton for the german developer community ;-)

http://bedifferently.wordpress.com/tag/uibutton/

have fun ;-)

reply

Fox
01/03/2012 - 16:30

nice tutorial! I believe you are the one who could answer this tricky thing to :p
Im using a for-loop that uses a similar code to this one you are describing. Im also using storyboard which make everything a bit trickier.

What I'm trying to do is to make these buttons take the user to one and the same scene in the storyboard but with different id´s sent with them. Lets say there will be 3 buttons that will be printed. One with the ID 1, one with ID 2 and one with ID 3 so that i can chose what picture will be shown in the next scene.

I hope that my explanation is not too vague. I really need help with this. Thank you so much in advance!!

//FOX

reply

Fox
01/03/2012 - 18:33

I will try to clarify what I'm looking for.

1. My app uses Storyboard and have segues to everything but one scene. This scene should only be connected to these buttons I'm looping out. Therefore i can't make a connection in the Storyboard. I have one scene that is not connected with a segue at all. But its connected to view controller files (.h and .m).

2. In another view controller file (.m) I'm looping out:
- (void)viewDidLoad
{
[super viewDidLoad];

int heightGrowt = 0;

for(int i = 0; i < 10; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];

button.frame = CGRectMake(10, heightGrowt, 300, 40);

heightGrowt = heightGrowt + 50;

[button setTitle:@"First element" forState:UIControlStateNormal];
[button setTag:i];

[button addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

[scrollWiew addSubview:button];
}

[scrollWiew setScrollEnabled:YES];
[scrollWiew setContentSize:CGSizeMake(320, heightGrowt)];
}

-(void)buttonPressed:(id)Sender
{
UIButton *button = (UIButton *)Sender;
int id_ = button.tag;
NSLog(@"the tag value is: %d", id_);

}

3. From the buttonPressed function i wanna get a new view shown with a picture. the id_ variable will help me identify which picture.

I hop this is more explaining than my last post.

reply

Add Comment

Put code snippets inside language tags:
[language] [/language]

Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]

See here for supported languages.

Javascript must be enabled to submit anonymous comments - or you can login.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.