Establecer una imagen de fondo para una tabbar

Estoy tratando de establecer programáticamente la imagen de fondo para una barra de tabs en mi aplicación. Mi código es el siguiente:

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]; } 

Esto no funciona para mí

ACTUALIZAR

ACTUALIZACIÓN 23 de enero de 2012

Ok, he hecho un poco de progreso. Esto solo dejó de funcionar desde que actualicé a Xcode 4.2 e IOS5. Logré recuperarlo usando las opciones en Interface Builder, pero ahora solo funciona para IOS5. Idealmente, me hubiera gustado trabajar programáticamente, pero me conformaré con la solución IB por ahora.

Parece que no puedo hacer que funcione para lanzamientos anteriores.

NOTA: mi TabBar está solo en mi RootViewController, que es la pantalla principal de mi aplicación.

Idealmente, si pudiera hacer funcionar el código que Nithin sugirió, sería genial:

 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]; 

Cualquier ayuda sería apreciada.

Saludos, Stephen

    Puede usar una clase personalizada para UITabBarController y anular su tabBarController. Allí puede configurar los botones requeridos y sus acciones con la imagen.

    Así es como se puede ver la clase de controlador de la barra de tabs personalizada:

    // CustomTabBarController.h

     #import  @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 

    Espero que esto te ayude mucho.

     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]; 

    Deberá codificar condicionalmente esto por versión del sistema operativo.

    Si solo admite iOS 5, puede simplemente usar la propiedad backgroundImage de la barra de tabs. Si necesita admitir versiones de iOS por debajo de 5, debe agregar un código condicional que lo ‘piratee’. Hay varios enfoques para hacer eso, aquí hay uno:

    Imagen de fondo de la barra de tabs personalizada: en iOS 4.x

    Tomado de: 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]]; 

    Como mencioné antes en iOS 5, le sugiero que use la imagen de fondo:

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

    Siempre use un cheque como respondsToSelector lugar de la verificación de versión explícita. Esto da como resultado un código más seguro y más a prueba de futuro.

    En iOS 4, le sugiero que utilice el método -[UITabBar drawRect:] , preferiblemente en una subclase. Luego, en Interface Builder, configure la clase personalizada UITabBarController s UITabBar (generalmente en MainWindow.xib) en su subclase personalizada.

    Sin embargo, si no está utilizando MainWindow.xib y, al igual que las plantillas de códigos iOS 5, genera su UITabBarController en el código, solo puede sobrescribir el método drawRect: utilizando una categoría en 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 

    Esto solo funciona en los sistemas iOS 4.xy anteriores, pero eso está bien porque ya cubrimos iOS 5.

    Solo tienes que identificar cada caso, verificando la versión con -respondToSelector como dijo Vinodh. Te sugiero que crees una categoría en UITabBar y lo hagas fácil. Entonces el código tendrá esta forma:

      // UITabBar+Custom.h #import  #import  @interface UITabBar (Custom) -(void)setTabBarBackground:(UIImage *)backgroundImage; @end 

    Y el archivo .m:

      // UITabBar+Custom.m #import "UITabBar+Custom.h" #import  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(); } 

    El -drawLayer:inContext dibujará la imagen de fondo rápidamente.

    Como respondí anteriormente, sin agregar UIView es posible agregar la imagen de fondo a una UITabBar, una imagen que podría desaparecer al llamar a [tabBar setNeedsDisplay] , así que pensé en dibujar la imagen en -drawLayer:layer inContext:ctx (the -drawInRect:rect no se llama). Sin embargo, si puede evitar llamar a [tabBar setNeedsDisplay] , hay una forma simple de hacerlo:

     // UITabBar+Custom.m #import "UITabBar+Custom.h" #import  -(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; } } 

    Tome una vista personalizada y agréguela a la barra UITaB. ahora agregue el botón en esa vista y proporcione el enlace de método a los botones de la barra de tabs. Ahora puede hacer lo que quiera en esa vista agregando imagen o cualquier cosa. Funciona como una barra de tabs personalizada.

    Lo que hice en el pasado es crear mi propio TabbarController para cargar diferentes UIViewControllers . Con este controlador puedo manipular la apariencia de la barra de tabs y los elementos de barra de tabs en ella.

    Esto funciona bien para mí, pero inicialmente es un poco de trabajo. Porque tienes que “simular” el UITabBarController , ya que en realidad no usas la UITabBar ‘nativa’

      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]; } 
     // 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 } 
     // Change the tab bar background UIImage* tabBarBackground = [UIImage imageNamed:@"tabbar.png"]; [[UITabBar appearance] setBackgroundImage:tabBarBackground];