Stephen
Stephen

Reputation: 4813

Setting a background image for a tabbar

I'm trying to programmatically set the background image for a tabbar in my app. My code is as follows:

RootViewController.h

IBOutlet UITabBar *mainTabBar;
    IBOutlet UITabBarItem *settingsBarItem;
    IBOutlet UITabBarItem *infoBarItem;
    IBOutlet UITabBarItem *aboutBarItem;

RootViewController.m

-(void)viewDidLoad {

    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"smallMenuBackground.png"]];    
    [mainTabBar insertSubview:imageView atIndex:0];
    [imageView release];

    [super viewDidLoad];
}

This is not working for me.

UPDATE

UPDATE 23rd January 2012

Ok, I've made a bit of progress. This only stopped working since I upgraded to Xcode 4.2 and IOS5. I managed to get it back using the options in Interface Builder, but now it only works for IOS5. Ideally I would have liked to get working programatically but I'll settle for the IB solution for now.

I just can't seem to get it working for any previous releases.

NOTE: my TabBar is only on my RootViewController, which is the main screen of my app.

Ideally, if I could get the code working that Nithin suggested, that would be great:

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tabBG.png"]];

if ([[[UIDevice currentDevice] systemVersion] floatValue] > 4.9) {
    //iOS 5
    [self.tabBarController.tabBar insertSubview:imageView atIndex:1];
}
else {
    //iOS 4.whatever and below
    [self.tabBarController.tabBar insertSubview:imageView atIndex:0];
}

[imageView release];

Any help would be appreciated.

Regards, Stephen

Upvotes: 8

Views: 32594

Answers (12)

MarkP
MarkP

Reputation: 2566

Taken from: http://ios-blog.co.uk/tutorials/ios-custom-ui-series-tabbar-navbar/

// Change the tab bar background
UIImage *tabBarBackground = [UIImage imageNamed:@"CustomUITabbar.png"];
[[UITabBar appearance] setBackgroundImage:tabBarBackground];
[[UITabBar appearance] setTintColor:[UIColor whiteColor]];

Upvotes: 2

iKushal
iKushal

Reputation: 2889

// Change the tab bar background
 UIImage* tabBarBackground = [UIImage imageNamed:@"tabbar.png"];
 [[UITabBar appearance] setBackgroundImage:tabBarBackground];

Upvotes: 0

TheGreenFlag1
TheGreenFlag1

Reputation: 31

As I answered above, without adding UIView it's possible to add the background image to an UITabBar, an image which could disappear when you call [tabBar setNeedsDisplay], so I thought of draw the image in -drawLayer:layer inContext:ctx (the -drawInRect:rect is not called). However if you can avoid calling [tabBar setNeedsDisplay], there's a simple way of doing this:

// UITabBar+Custom.m

#import "UITabBar+Custom.h"
#import <QuartzCore/QuartzCore.h>

-(void)setTabBarBackground:(UIImage *)backgroundImage  {
     if([self respondsToSelector:@selector(setBackgroundImage:)]) {
          // ios 5+
          [self setBackgroundImage:backgroundImage];
     }  else  {
          // ios 3.x / 4.x
          self.layer.contents = (id)backgroundImage.CGImage;
     }
}

Upvotes: 1

TheGreenFlag1
TheGreenFlag1

Reputation: 31

You just have to identifying each case, checking the version with -respondToSelector as Vinodh said. I suggest you to create a category on UITabBar and do it easy. So the code will have this form:

    // UITabBar+Custom.h

    #import <UIKit/UIKit.h>
    #import <QuartzCore/QuartzCore.h>

    @interface UITabBar (Custom)
    -(void)setTabBarBackground:(UIImage *)backgroundImage;
    @end

And the .m file:

    // UITabBar+Custom.m

    #import "UITabBar+Custom.h"
    #import <objc/runtime.h>

    static char *backgroundImageKey;

    -(void)setImage:(UIImage *)anImage  {
          objc_setAssociatedObject(self, &backgroundImageKey, 
                anImage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
          [self setNeedsDisplay];
    }

    -(UIImage *)image  {
          return objc_getAssociatedObject(self, &backgroundImageKey);
    }

    -(void)setTabBarBackground:(UIImage *)backgroundImage  {
         if([self respondsToSelector:@selector(setBackgroundImage:)]) {
              [self setBackgroundImage:backgroundImage];
         }  else  {
              [self setImage:backgroundImage];
         }
    }

    -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx  {
        UIGraphicsPushContext(ctx);
        UIImage *currentImage = [self image];
        CGContextTranslateCTM(ctx, 0, currentImage.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);

        CGContextDrawImage(ctx, self.bounds, currentImage.CGImage);
        UIGraphicsPopContext();
    }

The -drawLayer:inContext will draw the background image fast.

Upvotes: 1

Joris Kluivers
Joris Kluivers

Reputation: 12081

Like mentioned before on iOS 5 I would suggest you use the background image:

UITabBar *tabBar = tabController.tabBar;
if ([tabBar respondsToSelector:@selector(setBackgroundImage:)]) {
    tabBar.backgroundImage = [UIImage imageNamed:@"TabBackground.png"];
}

Always use a check like respondsToSelector instead of explicit version checking. This results in safer and more future proof code.

On iOS 4 I would suggest you use the -[UITabBar drawRect:] method, preferably in a subclass. Then in Interface Builder set the UITabBarControllers UITabBar custom class (usually in MainWindow.xib) to your custom subclass.

However if you are not using a MainWindow.xib, and like the iOS 5 code templates you generate your UITabBarController in code, you can only overwrite the drawRect: method using a category on UITabBar.

// UITabBar+CustomBackground.h
@interface UITabBar (CustomBackground)
@end

// UITabBar+CustomBackground.m
@implementation UITabBar (CustomBackground)
- (void) drawRect:(CGRect)frame {
    [[UIColor redColor] set];

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextFillRect(ctx, [self bounds]);
}
@end

This only works on systems iOS 4.x and earlier, but thats ok because we covered iOS 5 already.

Upvotes: 1

Vinodh
Vinodh

Reputation: 5268

// not supported on iOS4    
UITabBar *tabBar = [tabController tabBar];
if ([tabBar respondsToSelector:@selector(setBackgroundImage:)])
{
    // set it just for this instance
    [tabBar setBackgroundImage:[UIImage imageNamed:@"tabbar_brn.jpg"]];

    // set for all
    // [[UITabBar appearance] setBackgroundImage: ...
}
else
{
    // ios 4 code here
}

Upvotes: 0

Piyush Kashyap
Piyush Kashyap

Reputation: 1965

 jUst call these two methods
   hideTabBar;
   addCustomElements;

  hideTabBar method hides the original tabbar
  And addCustomElements method will add the custom tabbar image as well as custom tabbar button also 


- (void)hideTabBar
{
    for(UIView *view in self.tabBarController.view.subviews)
    {
        //      if([view isKindOfClass:[UITabBar class]])
        //      {
        //          view.hidden = YES;
        //          break;
        //      }

        if([view isKindOfClass:[UITabBar class]])
        {
            [view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
        } 
        else 
        {
            [view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
        }


    }
}

-(void)addCustomElements
{
    // Initialise our two images
    UIImage *btnImage = [UIImage imageNamed:@"homet.png"];
    UIImage *btnImageSelected = [UIImage imageNamed:@"homehovert.png"];

    self.btn1 = [UIButton buttonWithType:UIButtonTypeCustom]; //Setup the button
    btn1.frame = CGRectMake(28, 446, 25,28); // Set the frame (size and position) of the button)
    [btn1 setBackgroundImage:btnImage forState:UIControlStateNormal]; // Set the image for the normal state of the button
    [btn1 setBackgroundImage:btnImageSelected forState:UIControlStateSelected]; // Set the image for the selected state of the button
    [btn1 setTag:0]; // Assign the button a "tag" so when our "click" event is called we know which button was pressed.
    [btn1 setSelected:true]; // Set this button as selected (we will select the others to false as we only want Tab 1 to be selected initially

    // Now we repeat the process for the other buttons
    btnImage = [UIImage imageNamed:@"blogt.png"];
    btnImageSelected = [UIImage imageNamed:@"bloghovert.png"];
    self.btn2 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn2.frame = CGRectMake(107, 448, 22,28);
    [btn2 setBackgroundImage:btnImage forState:UIControlStateNormal];
    [btn2 setBackgroundImage:btnImageSelected forState:UIControlStateSelected];
    [btn2 setTag:1];

    btnImage = [UIImage imageNamed:@"networkt.png"];
    btnImageSelected = [UIImage imageNamed:@"networkhovert.png"];
    self.btn3 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn3.frame = CGRectMake(180, 446, 35,29);
    [btn3 setBackgroundImage:btnImage forState:UIControlStateNormal];
    [btn3 setBackgroundImage:btnImageSelected forState:UIControlStateSelected];
    [btn3 setTag:2];

    btnImage = [UIImage imageNamed:@"contactt.png"];
    btnImageSelected = [UIImage imageNamed:@"contacthovert.png"];
    self.btn4 = [UIButton buttonWithType:UIButtonTypeCustom];
    btn4.frame = CGRectMake(262, 447, 32,28);
    [btn4 setBackgroundImage:btnImage forState:UIControlStateNormal];
    [btn4 setBackgroundImage:btnImageSelected forState:UIControlStateSelected];
    [btn4 setTag:3];

    self.img1 = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"tabbar.png"]] ;
    img1.frame = CGRectMake(0, 440, 320, 40); 




    [self.tabBarController.view addSubview:img1];
    // Add my new buttons to the view
    [self.tabBarController.view addSubview:btn1];
    [self.tabBarController.view addSubview:btn2];
    [self.tabBarController.view addSubview:btn3];
    [self.tabBarController.view addSubview:btn4];

    // Setup event handlers so that the buttonClicked method will respond to the touch up inside event.
    [btn1 addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [btn2 addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [btn3 addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [btn4 addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}

Upvotes: 0

Erfan
Erfan

Reputation: 1304

You can use custom class for UITabBarController & override your tabBarController. There you can set your required buttons & their actions with image.

This is how your custom tab bar controller class can be look like:

// CustomTabBarController.h

#import <UIKit/UIKit.h>

@interface CustomTabBarController : UITabBarController {
    UIButton *settingsButton;
    UIButton *infoButton;
    UIButton *aboutUsButton;
}

@property (nonatomic, retain) UIButton *settingsButton;
@property (nonatomic, retain) UIButton *infoButton;
@property (nonatomic, retain) UIButton *aboutUsButton;

-(void) addCustomElements;
-(void) selectTab:(int)tabID;

@end

// CustomTabBarController.m

#import "CustomTabBarController.h"

@implementation CustomTabBarController

@synthesize settingsButton, infoButton, aboutUsButton;

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];


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

-(void)addCustomElements
{
    // Background
    UIImageView* bgView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tabBarBackground.png"]] autorelease];
    bgView.frame = CGRectMake(0, 420, 320, 60);
    [self.view addSubview:bgView];

    // Initialise our two images
    UIImage *btnImage = [UIImage imageNamed:@"settings.png"];
    UIImage *btnImageSelected = [UIImage imageNamed:@"settingsSelected.png"];

    self.settingsButton = [UIButton buttonWithType:UIButtonTypeCustom]; //Setup the button
    settingsButton.frame = CGRectMake(10, 426, 100, 54); // Set the frame (size and position) of the button)
    [settingsButton setBackgroundImage:btnImage forState:UIControlStateNormal]; // Set the image for the normal state of the button
    [settingsButton setBackgroundImage:btnImageSelected forState:UIControlStateHighlighted]; // Set the image for the selected state of the button
    [settingsButton setBackgroundImage:btnImageSelected forState:UIControlStateSelected]; // Set the image for the selected state of the button
    [settingsButton setBackgroundImage:btnImageSelected forState:UIControlStateDisabled];
    [settingsButton setImage:btnImageSelected forState:(UIControlStateHighlighted|UIControlStateSelected)];
    [settingsButton setTag:101]; // Assign the button a "tag" so when our "click" event is called we know which button was pressed.
    [settingsButton setSelected:true]; // Set this button as selected (we will select the others to false as we only want Tab 1 to be selected initially

    // Now we repeat the process for the other buttons
    btnImage = [UIImage imageNamed:@"info.png"];
    btnImageSelected = [UIImage imageNamed:@"infoSelected.png"];
    self.infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
    infoButton.frame = CGRectMake(110, 426, 100, 54);
    [infoButton setBackgroundImage:btnImage forState:UIControlStateNormal];
    [infoButton setBackgroundImage:btnImageSelected forState:UIControlStateSelected];
    [infoButton setBackgroundImage:btnImageSelected forState:UIControlStateHighlighted];
    [infoButton setImage:btnImageSelected forState:(UIControlStateHighlighted|UIControlStateSelected)];

    [infoButton setTag:102];

    btnImage = [UIImage imageNamed:@"aboutUs.png"];
    btnImageSelected = [UIImage imageNamed:@"aboutUsSelected.png"];
    self.aboutUsButton = [UIButton buttonWithType:UIButtonTypeCustom];
    aboutUsButton.frame = CGRectMake(210, 426, 100, 54);
    [aboutUsButton setBackgroundImage:btnImage forState:UIControlStateNormal];
    [aboutUsButton setBackgroundImage:btnImageSelected forState:UIControlStateSelected];
    [aboutUsButton setBackgroundImage:btnImageSelected forState:UIControlStateHighlighted];
    [aboutUsButton setImage:btnImageSelected forState:(UIControlStateHighlighted|UIControlStateSelected)];

    [aboutUsButton setTag:103];

    // Add my new buttons to the view
    [self.view addSubview:settingsButton];
    [self.view addSubview:infoButton];
    [self.view addSubview:aboutUsButton];

    // Setup event handlers so that the buttonClicked method will respond to the touch up inside event.
    [settingsButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [infoButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [aboutUsButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
}

- (void)buttonClicked:(id)sender
{
    int tagNum = [sender tag];
    [self selectTab:tagNum];
}

- (void)selectTab:(int)tabID
{
    switch(tabID)
    {
        case 101:
            [settingsButton setSelected:true];
            [infoButton setSelected:false];
            [aboutUsButton setSelected:false];
            break;
        case 102:
            [settingsButton setSelected:false];
            [infoButton setSelected:true];
            [aboutUsButton setSelected:false];
            break;
        case 103:
            [settingsButton setSelected:false];
            [infoButton setSelected:false];
            [aboutUsButton setSelected:true];
            break;
    }   
    self.selectedIndex = tabID;
}

- (void)dealloc {
    [settingsButton release];
    [infoButton release];
    [aboutUsButton release];

    [super dealloc];
}

@end

Hope this will help you a lot.

Upvotes: 14

basvk
basvk

Reputation: 4546

What I've done in the past is create my own TabbarController to load different UIViewControllers. With this controller I can manipulate the appearance of the tabbar and tabbar items in it.

This works fine by me, but it's initially a bit of work. Because you have to "simulate" the UITabBarController, since you don't actually use the 'native' UITabBar

Upvotes: 0

nithin
nithin

Reputation: 2467

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tabBG.png"]];

if ([[[UIDevice currentDevice] systemVersion] floatValue] > 4.9) {
    //iOS 5
    [self.tabBarController.tabBar insertSubview:imageView atIndex:1];
}
else {
    //iOS 4.whatever and below
    [self.tabBarController.tabBar insertSubview:imageView atIndex:0];
}

[imageView release];

Upvotes: 7

lxt
lxt

Reputation: 31304

You will need to conditionally code this by OS version.

If you are only supporting iOS 5, you can simply use the backgroundImage property of the tabbar. If you need to support versions of iOS below 5 you should add some conditional code that 'hacks' it in place. There are several approaches to do that, here's one:

Custom tab bar background image - in iOS 4.x

Upvotes: 3

Madhu
Madhu

Reputation: 1542

Take a customized view and add it on UITaB bar. now add button on that view and provided method link to tab bar buttons. Now u can do whatever on that view by adding image or any thing. It works as like Customized tab bar.

Upvotes: 0

Related Questions