MOBILE

Programming the iPhone : Standard Control Types (part 1) - Buttons

8/4/2012 3:14:33 PM
One perk of Cocoa Touch is the collection of control classes in UIKit. A user interface control pattern includes one or more user interface elements that work together to solve an input problem. It’s clear that Apple put a lot of thought into the design of its controls, and developers can easily take advantage of that work. This section will introduce you to the most common types of controls.

1. Buttons

The simplest controls are buttons. The UIButton class is the foundation for most buttons, including custom button subclasses. Buttons are used extensively in Cocoa Touch applications and can be customized through display attributes or with specialized drawing code.

1.1. Creating buttons

You can use the buttonWithType: method of UIButton to create buttons of several different types. Table 1 describes the various UIButtonType keys.

Table 1. UIButtonType keys
UIButtonType keyDescription
UIButtonTypeCustomNo button style. Instead, a custom drawRect: method should be defined.
UIButtonTypeRoundedRectA rectangular button with rounded corners and a centered title. Used for all general-purpose buttons.
UIButtonTypeDetailDisclosureA circular button with a centered chevron (>). Used to display details of an associated object or record.
UIButtonTypeInfoLightA light-colored, circular button with an italicized lowercase “i” character. Used to flip a view over to display settings or additional information.
UIButtonTypeInfoDarkA dark-colored, circular button with an italicized lowercase “i” character. Used to flip a view over to display settings or additional information.
UIButtonTypeContactAddA rectangular button with rounded corners and a centered title. Used to display either a list of contacts or a form for adding a new contact.

Creating and customizing buttons is easy with the UIButton class. Custom subclasses of UIButton allow developers to use more attractive buttons in their applications. In this example, a special UIButton subclass, PrettyButton, assigns special images to be used for the two main button states: UIControlStateNormal and UIControlStateHighlighted. The supplied images are used as stretchable graphics by invoking the stretchableImageWithLeftCapWidth:topCapHeight: method of UIImage. Stretchable images use the concept of caps to lock a portion of the left, right, top, and bottom of a graphic as non-stretchable, while allowing the center area outside of the caps to grow as needed:

// PrettyButton.h

#import <Foundation/Foundation.h>

@interface PrettyButton : UIButton {
	UIImage *standardImg;
	UIImage *hoverImg;
}

@end

// PrettyButton.m

#import "PrettyButton.h"

@implementation PrettyButton

- (id)init
{
	if(self = [super init]){
		if(!standardImg){
			UIImage *image = [UIImage imageNamed:@"standard.png"];
			standardImg = [image stretchableImageWithLeftCapWidth:12
													 topCapHeight:12];
		}
		
		if(!hoverImg){
			UIImage *image = [UIImage imageNamed:@"hover.png"];
			hoverImg = [image stretchableImageWithLeftCapWidth:12
												  topCapHeight:12];
		}
		
		[self setBackgroundImage:standardImg forState:UIControlStateNormal];
		[self setBackgroundImage:hoverImg forState:UIControlStateHighlighted];
		[self setTitleColor:[UIColor colorWithRed:.208
											green:.318
											 blue:.525
											alpha:1.0]
				   forState:UIControlStateNormal];
		[self setTitleColor:[UIColor whiteColor]
				   forState:UIControlStateHighlighted];
		self.titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold"
											   size:15.0];
		self.titleLabel.textAlignment = UITextAlignmentCenter;
	}
	return self;
}
@end


					  

// ButtonsViewController.h

#import <UIKit/UIKit.h>

@interface ButtonsViewController : UIViewController {
}

- (void)createStandardButton;
- (void)createPrettyButton;
- (void)standardButtonPressed:(id)sender;
- (void)prettyButtonPressed:(id)sender;

@end

// ButtonsViewController.m

#import "ButtonsViewController.h"
#import "PrettyButton.h"

@implementation ButtonsViewController

- (void)viewDidLoad
{
	[super viewDidLoad];
	[self createStandardButton];
	[self createPrettyButton];
}

#pragma mark Standard button and click handler
- (void)createStandardButton
{
	// Create a button with a rounded-rectangle style
	UIButton *standardButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	float x = 30.0;
	float y = 30.0;
	float width = 120.0;
	float height = 40.0;
	// Create the frame that determines the size of the button
	CGRect frame = CGRectMake(x, y, width, height);
	standardButton.frame = frame;
	// Set the title of the button for the normal state
	[standardButton setTitle:@"Standard" forState:UIControlStateNormal];
	// Add self as a target
	[standardButton addTarget:self action:@selector(standardButtonPressed:)
			 forControlEvents:UIControlEventTouchUpInside];
	// Set the button as a subview of my view
	[self.view addSubview:standardButton];
}

- (void)standardButtonPressed:(id)sender
{
	NSLog(@"Standard button pressed.");
}

#pragma mark Pretty button and click handler
- (void)createPrettyButton
{
	// Create an instance of a custom button subclass
	PrettyButton *prettyButton = [[PrettyButton alloc] init];
	float x = 170.0;
	float y = 30.0;
	float width = 120.0;
	float height = 40.0;
	// Create the frame that determines the size of the button
	CGRect frame = CGRectMake(x, y, width, height);
	prettyButton.frame = frame;
	// Set the title of the button for the normal state
	[prettyButton setTitle:@"Custom" forState:UIControlStateNormal];
	// Add self as a target
	[prettyButton addTarget:self action:@selector(prettyButtonPressed:)
		   forControlEvents:UIControlEventTouchUpInside];
	// Set the button as a subview of my view
	[self.view addSubview:prettyButton];
	[prettyButton release];
}

- (void)prettyButtonPressed:(id)sender
{
	NSLog(@"Pretty button pressed.");
}

@end


					  

Figure 1 shows the results of this application: a standard UIButton with rounded corners, and a custom UIButton subclass with PNG files as background images.

1.2. Info buttons

Many iPhone applications fit into the category of lightweight utilities. These apps tend to be very simple in their presentation of information and require very little interaction. The utility application Xcode template provided by the iPhone SDK is typically the foundation of such apps. One common feature of utilities is the presence of a small icon that displays the letter “i” and acts as a button to display more information about the application. Additional information is most often displayed after a “flip” animation that reverses the view. This pattern is well known because it is the default behavior of the utility application template, and because Apple uses it in official iPhone applications such as the Weather application, as shown in Figure 2.

Figure 1. A standard UIButton and a custom UIButton subclass with a custom background


Figure 2. The Weather application features an information button in the lower-right corner


You can add an info button to your views by passing UIButtonTypeInfoLight or UIButtonTypeInfoDark to the static buttonWithType method of the UIButton class:

UIButton *lightButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
UIButton *darkButton = [UIButton buttonWithType:UIButtonTypeInfoDark];

You can wire an information button to flip a view using Core Animation. In this example, the class FlipperView represents a main view on the screen. It in turn contains two subviews. The frontView variable is a pointer to an instance of FrontView, a UIView subclass. The backView variable is a pointer to an instance of BackView, also a UIView subclass. When the toggle method is called, an animation transaction is created and a transition is assigned to the FlipperView instance:

// FrontView.h

#import <UIKit/UIKit.h>

@interface FrontView : UIImageView {
}

@end

#import "FrontView.h"
#import "FlipperView.h"

@implementation FrontView

#define PADDING 10.0

- (id)initWithFrame:(CGRect)frame
{
	if (self = [super initWithFrame:frame]) {
		infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
		[infoButton addTarget:self action:@selector(showInfo:)
			forControlEvents:UIControlEventTouchUpInside];
		infoButton.center = CGPointMake(
			self.frame.size.width - infoButton.frame.size.width/2 - PADDING,
			self.frame.size.height - infoButton.frame.size.height/2 - PADDING
		);
		[self addSubview:infoButton];
		self.backgroundColor = [UIColor clearColor];
		self.image = [UIImage imageNamed:@"front.png"];
		self.userInteractionEnabled = YES;
	}
	return self;
}

- (void)showInfo:(id)sender
{
	[(FlipperView *)self.superview toggle];
}

@end


					  

// FlipperView.h

#import <UIKit/UIKit.h>

@class FrontView;
@class BackView;

@interface FlipperView : UIView {
	BOOL isFlipped;
	FrontView *frontView;
	BackView *backView;
}

@property (assign) BOOL isFlipped;

- (void)toggle;

@end

// FlipperView.m

#import "FlipperView.h"
#import "FrontView.h"
#import "BackView.h"

@implementation FlipperView

@synthesize isFlipped;

- (id)initWithFrame:(CGRect)frame
{
	if(self = [super initWithFrame:frame]){
		frontView = [[FrontView alloc] initWithFrame:self.frame];
		backView = [[BackView alloc] initWithFrame:self.frame];

		//	Add the front view as the main content to start off.
		[self addSubview:frontView];

		//	Insert the back view under the front view, hidden.
		[self insertSubview:backView belowSubview:frontView];
		
		self.backgroundColor = [UIColor clearColor];
		self.clipsToBounds = YES;
	}
	return self;
}

- (void)toggle
						{
							[UIView beginAnimations:nil context:NULL];
							[UIView setAnimationDuration:1];
							UIViewAnimationTransition direction;
							if(isFlipped){
								direction = UIViewAnimationTransitionFlipFromLeft;
								isFlipped = NO;
							}else{
								direction = UIViewAnimationTransitionFlipFromRight;
								isFlipped = YES;
							}
							//	Mid-animation, swap the views.
							[self exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
							[UIView setAnimationTransition:direction forView:self cache:YES];
	[UIView commitAnimations];
						}

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


@end


					  

You should be careful having an information button trigger views outside of the flip, though you needn’t necessarily avoid it. As with most user experience programming for Cocoa Touch, it’s best to stick to the known paths and perfect the nuances, but at the same time you shouldn’t hesitate to evaluate new patterns.
Other  
  •  Sony Introduced 3 New Phones In Xperia Series: Tipo, Miro And Ion
  •  Samsung Galaxy SIII And HTC One X: A Detailed And Thorough Comparison
  •  In Control
  •  BlackBerry Virtual Keyboard: The Development Through Each Appliance
  •  3D Phone – Why Is LG Optimus 3D Max P725 The Best Choice, Still?
  •  XNA Game Studio 4.0 : Xbox 360 Gamepad (part 2) - Moving Sprites Based on Gamepad Input
  •  XNA Game Studio 4.0 : Xbox 360 Gamepad (part 1) - Reading Gamepad State
  •  XNA Game Studio 4.0 : Adding Interactivity with User Input - Precision Control of a Mouse
  •  Asus Transformer Pad TF300
  •  Mobile Phone Game Programming : Using Sprite Animation - Building the UFO Example Program
  •  Mobile Phone Game Programming : Using Sprite Animation - Achieving Smooth Animation with the GameCanvas Class
  •  Mobile Phone Game Programming : Using Sprite Animation - Working with the Layer and Sprite Classes
  •  Windows Phone 8 Unveiled
  •  iOS 6 Beta Review (Part 2)
  •  iOS 6 Beta Review (Part 1)
  •  Ipad : Tabletop
  •  Ipad Lion (Part 3) - Other possible features
  •  Ipad Lion (Part 2) - What to expect from the upcoming mountain lion
  •  Ipad Lion (Part 1) - Lion paving the way for mountain lion's destiny
  •  The Effect Of IOS And Facebook On Shutterbugs (Part 2)
  •  
    Top 10
    What To Look For When Buying A New Phone Or Tablet (Part 10)
    What To Look For When Buying A New Phone Or Tablet (Part 9)
    What To Look For When Buying A New Phone Or Tablet (Part 8)
    What To Look For When Buying A New Phone Or Tablet (Part 7)
    What To Look For When Buying A New Phone Or Tablet (Part 6)
    What To Look For When Buying A New Phone Or Tablet (Part 5)
    What To Look For When Buying A New Phone Or Tablet (Part 4)
    What To Look For When Buying A New Phone Or Tablet (Part 3)
    What To Look For When Buying A New Phone Or Tablet (Part 2)
    What To Look For When Buying A New Phone Or Tablet (Part 1)
    Most View
    Microsoft ASP.NET 3.5 : The HTTP Request Context - The global.asax File
    Fujifilm XF1 - Compact Camera With Retro Design
    Samsung MV900F
    MSI GT70 Notebook - Power Play
    Windows 7 : Maintaining Your Hard Drive
    AMD And Nvidia Based Products In The New Benchmark (Part 1)
    HP X7000 Wi-Fi Touch Mouse - The Wi-Fi Touch
    WCF Services : Enumerations
    SQL Server 2008 : What Is the Base Class Library?
    Windows 7 : Indexing Your Computer for Faster Searches (part 1) - Adding or Removing Indexed Locations
    Microsoft Dynamics AX 2009 : Building Lookups - Displaying a list of custom options
    Undelete 10 - Fairly Easy To Use
    Cutting Edge Technology (Part 3)
    Google Nexus 4 Smartphone - Coming Of Age On The Fourth Try
    Visual Studio 2010 : Introducing the Visual Studio Extensibility - Building a Visual Studio Package
    A Click Away From Malware
    OS X Mountain Lion: What’s New - The System (Part 8)
    The choices of mobile computing for SOHO users (part 1)
    Samsung ATIV Odyssey Review - A Good Budget WP8 Phone (Part 1)
    Group Test: Free Office Suites (Part 3) - LibreOffice