Saturday, August 31, 2013

Custom Back Button UINavigationBar

Custom Back Button - UINavigationBar

Custom Back Button - UINavigationBar

IOS comes with useful controls for developers which makes app development and UI navigation pretty easy.

One of such controls is the UINavigationController.

UINavigationController allows you to push ViewControllers onto a stack. It comes with a UINavigationBar which automatically contains back button to go to the previous View from the current view.

Using UINavigationController is common is most ios apps.

The back button which is a UIBarButtonItem usually comes with the defaut chrome for the IOS app.

However, if you have a different design for your app, you may as well want to have a custom back button.

There are two ways to do this:

1) Change the background Image of the back button

2) Create a custom UIBarButtonItem as the back button (and hide the original back button)

This post will focus on the second method. The first method works in situations where you dont want to change the text on the back button, just the background image or the theme.

UINavigationBar

The UINavigationBar is the top bar that's is automatically placed at the top of UINavigationController to allow for navigating back and forth.

The UINavigationBar of a UINavigationController can be accessed (from a UIViewController)

self.navigationItem

So to get our custom back button we are basically doing this;

  1. Hide the default back button
  2. Create a custom UIBarButtonItem
  3. Add it to the UINavigationBar

Another thing we need to do is to ensure we do steps 2 and 3 only when we have are on a view other than the first on the stack.

  1. Create a new single view application from Xcode
  2. Add UIViewController call it BaseUIViewContoller

In BaseUIViewController.m, make the following changes to the default viewDidLoad method

    -(void)viewDidLoad
    {
        [super viewDidLoad];
        //hide the default back button 
        [self.navigationItem setHidesBackButton:YES];
    }
  1. We are going to add a method that will create a custom UIBarButtonItem using our custom back button image

In BaseUIViewContoller.h add this

    -(UIBarButtonItem*)barButtonWithImage:(UIImage*)image 
    target:(id)target 
    action:(SEL)action;

In BaseUIViewController.m add this for the implementation of the method

    -(UIBarButtonItem*)barButtonWithImage:(UIImage*)image 
    target:(id)target 
    action:(SEL)action
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

    [button setBackgroundImage: [image stretchableImageWithLeftCapWidth:7.0 topCapHeight:0.0] forState:UIControlStateNormal];

    [button setBackgroundImage:image forState:UIControlStateHighlighted];

    button.frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    [button addTarget:self action:action  forControlEvents:UIControlEventTouchUpInside];

    UIView *v=[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, image.size.width, image.size.height) ];

    [v addSubview:button];

    UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:v];

    return barButton;
    }

Finally lets add another method that will show the back button only when we are not on the first ViewController in a NavigationViewController

Remember we are hidding the back button. However, the navigationItem property of the UIViewController has leftButtonItems which is array of buttons that will appear left side of the UINavigationBar. So we ca add our custom UIBarButtonItem to this array and have it act as our back button!

In BaseUIViewController.h add this

-(void)setupBackButton;
-(void)goBack;

In BaseUIViewController.m add this for the implementation of the method

-(void)setupBackButton{
    if(self.navigationController && 
        [self.navigationController.childViewControllers count]>1){
        UIBarButtonItem *back = 
        [self barButtonWithImage:[UIImage imageNamed:@"Back"]
         target:self action:@selector(goBack)];
        self.navigationItem.leftBarButtonItems = 
        [NSArray arrayWithObjects:back, nil];
}
-(void)goBack{
    [self.navigationController popViewControllerAnimated:YES];
}

Now we will make all our UIViewControllers inherit from our BaseUIViewController.

In any of our UIViewControllers viewDidLoad method we can call the setupBackButton and that will put our back button in the nav bar.

-(void)viewDidLoad{
    [super viewDidLoad];
    [self setupBackButton];
    //do other stuff...
}

This will setup the back button and allows you to navigate back in the UINavigationController views.

Hope this helps.

Thanks for reading