In this episode, I decompose the Foursquare UI and recreate the custom navigation bar, using the iOS 5 customization APIs. You'll see how to set a custom background image, a title view that you can tap on, a custom bar button item, and a custom back button style.
Episode Links Source Code UINavigationBar Class Reference Setting a custom background graphic // CustomNavBar.m UIImage *navBarBg = [UIImage imageNamed:@"navigationbar.png"]; [self setBackgroundImage:navBarBg forBarMetrics:UIBarMetricsDefault]; Creating the title view - (void)viewDidLoad { self.navigationItem.titleView = [self titleView]; ... } - (UIView *)titleView { CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height; CGFloat width = 0.95 * self.view.frame.size.width; UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, navBarHeight)]; UIImage *logo = [UIImage imageNamed:@"logo.png"]; UIButton *logoButton = [UIButton buttonWithType:UIButtonTypeCustom]; CGFloat logoY = floorf((navBarHeight - logo.size.height) / 2.0f); [logoButton setFrame:CGRectMake(0, logoY, logo.size.width, logo.size.height)]; [logoButton setImage:logo forState:UIControlStateNormal]; UIImage *bubble = [UIImage imageNamed:@"notification-bubble-empty.png"]; UIImageView *bubbleView = [[UIImageView alloc] initWithImage:bubble]; const CGFloat Padding = 5.0f; CGFloat bubbleX = logoButton.frame.size.width + logoButton.frame.origin.x + Padding; CGFloat bubbleY = floorf((navBarHeight - bubble.size.height) / 2.0f); CGRect bubbleRect = bubbleView.frame; bubbleRect.origin.x = bubbleX; bubbleRect.origin.y = bubbleY; bubbleView.frame = bubbleRect; [containerView addSubview:logoButton]; [containerView addSubview:bubbleView]; return containerView; } Creating the custom right button item - (void)viewDidLoad { ... self.navigationItem.rightBarButtonItem = [self checkInButton]; ... } - (UIBarButtonItem *)checkInButton { UIImage *checkInImage = [UIImage imageNamed:@"global-checkin-button.png"]; UIImage *checkInPressed = [UIImage imageNamed:@"global-checkin-button-pressed.png"]; UIButton *checkInButton = [UIButton buttonWithType:UIButtonTypeCustom]; [checkInButton setBackgroundImage:checkInImage forState:UIControlStateNormal]; [checkInButton setBackgroundImage:checkInPressed forState:UIControlStateHighlighted]; const CGFloat BarButtonOffset = 5.0f; [checkInButton setFrame:CGRectMake(BarButtonOffset, 0, checkInImage.size.width, checkInImage.size.height)]; UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, checkInImage.size.width, checkInImage.size.height)]; [containerView addSubview:checkInButton]; UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:containerView]; return item; } Creating the custom back button item // CustomNavBar.m + (void)initialize { const CGFloat ArrowLeftCap = 14.0f; UIImage *back = [UIImage imageNamed:@"nav-backbutton.png"]; back = [back stretchableImageWithLeftCapWidth:ArrowLeftCap topCapHeight:0]; [[UIBarButtonItem appearanceWhenContainedIn:[CustomNavigationBar class], nil] setBackButtonBackgroundImage:back forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; const CGFloat TextOffset = 3.0f; [[UIBarButtonItem appearanceWhenContainedIn:[CustomNavigationBar class], nil] setBackButtonTitlePositionAdjustment:UIOffsetMake(TextOffset, 0) forBarMetrics:UIBarMetricsDefault]; }