Solved

Disable Tab Bar Item

Posted on 2010-09-08
19
2,349 Views
Last Modified: 2013-11-25
Is there a way to press a button and make one of the tab bar buttons disable or change the view of that tab bar item?
0
Comment
Question by:BTMExpert
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 9
19 Comments
 
LVL 2

Expert Comment

by:tisaksen
ID: 33630700
You will have to swap it out with a new UITabBarItem.
Just create a new vUITabBarItem object and replace the object you don't want to hang around in the tabbar.
Set the new item array using the UITabBar.items property.

There is no way to disable an item. You can create another view and put that on top of the view you want disabled though. Make sure it does not propagate it's touch events to the view below it. (Not sure if it will by default anyway)
0
 

Author Comment

by:BTMExpert
ID: 33640314
Thank you for the answer.  Can you show me how to do that.  I'm new to xcode.
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33640416
Which one, the replacing of an item or the creation of a new view which will be placed on top of the item you want to disable?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:BTMExpert
ID: 33640514
replacing the view will be great.  So when the user clicks the tab bat item it goes to another view right?
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33640766
This is the code to replace an item:

// create a new UITabBarItem, you decide what value you want to use for tagForNewItem
UITabBarItem *newItem = [[UITabBarItem alloc] initWithTitle:@"Title" image:someImageObject tag:tagForNewItem];
// create a mutable array with the tab bar items
NSMutableArray *barItems = [NSMutableArray arrayWithArray:self.tabBar.items];
// replace item, you must figure out the index of the object,
// typically you would use item.tag when you replace the item when it is clicked but
// otherwise you'll have to find a way to identify it's position in the array to be able to replace it.
[barItems replaceObjectAtIndex:item.tag withObject:newItem];
// set the new item list
self.tabBar.items = barItems;
// don't leak
[newItem release];

Then in -(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
you need to check the tag of the newly created item to decide what to do when the item is clicked.

Example:

-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
      switch(item.tag)
      {
            case tagForNewItem:
                  // perform your view change code here
            break;
            .......
      }
}
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33640870
I'm thinking maybe I didn't understand your question.
Is this what you wanted?
0
 

Author Comment

by:BTMExpert
ID: 33641018
i think you got it just one more thing to understand it better.  So the first part grabs the array of items in the tab bar and puts them in an array.  Then from there i replace the first item in the array, since that's the one i'm changing.  How does it know which ViewController and which nib file i want for the new tab bat item?

let me explain
i want the user to be able to click the first tab bar item, then click a button inside that view that sends them to another view that's on the tab bar.  when the user tries to click the first tab bar item again, it should change the view to a different first view.

i think you got it so i'm guessing the method that you sent me changes the view to what i want inside the case switch function
0
 

Author Comment

by:BTMExpert
ID: 33641045
Is there a difference between using UITabBar vs. UITabBarController.  I'm using TabBarController since that's what comes with the template.

still a beginner. sorry.
0
 
LVL 2

Accepted Solution

by:
tisaksen earned 500 total points
ID: 33641322
Yeah I think UITabBarController is made for conventient handling of UITabBar's. I have never used it so I can't say much about it.

Anyway, the key here is to use the delegate method (UITabBarDelegate)


-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
      switch(item.tag)
      {
            case 0:
                  // first item
                  // display the view you want the first time
                  YourViewController *ctrl = .........;
                  // addSubview or whatever you use to display it (might be a navigationController, I dont know)
            break;
            case 1:
                  // second item
            break;
            case 2:
                  // third item
                  // let's say this is the one which presents your view with a button,
                  // that when clicked, should replace the first item on the tabbar
                  // in the replace tabbar item code, set the tag of the new item to some far out value, like 9999 or whatever
                  // ie: UITabBarItem *newItem = [[UITabBarItem alloc] initWithTitle:@"Title" image:someImageObject tag:9999];
            break;
            case 9999:
                  // display the different view when the user clicks the first item on the tab bar
                  DifferentViewForFirstTabBarItem *differentView = .....
                  // addSubview or whatever you use to display it (might be a navigationController, I dont know)
                  // if you need to replace the first tab bar item again remember to set it's tag to 0 this time.
            break;
            
            // .........
      }
}

0
 

Author Comment

by:BTMExpert
ID: 33641507
NSMutableArray *barItems = [NSMutableArray arrayWithArray:self.tabBar.items];
do i have to declare tabBar as something like UITabBarItem.  it keeps throwing an error
0
 

Author Comment

by:BTMExpert
ID: 33641527
is that -(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
in the AppDelegate.m or on the view?
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33641613
You have to assign a delegate for your UITabBar, typically this delegate is the view controller that created it.

UITabBar *tabBar = ....;
tabBar.delegate = self;

Make sure you implement the protocol in your .h file:

@interface ViewControllerName <UITabBarDelegate>

Then put the didSelectItem: method in the .m file
0
 

Author Comment

by:BTMExpert
ID: 33641754
By doing it that way will i have to declare the UITabBar in every ViewController?
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33641791
In every view controller you need to use it yes. But you can of course use the AppDelegate for the delegate and to store the UITabBar reference too.
0
 

Author Comment

by:BTMExpert
ID: 33646685
For whatever reason i can't get it to work.  Should i send you my code so you can see or find what i'm missing?
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33647970
Send me your project and I will have a look.
0
 

Author Comment

by:BTMExpert
ID: 33648415
AppDelegate.h
#import <UIKit/UIKit.h>

@interface TabTestAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
    UIWindow *window;
    UITabBarController *tabBarController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

@end

AppDelegate.m
#import "TabTestAppDelegate.h"


@implementation TabTestAppDelegate

@synthesize window;
@synthesize tabBarController;


#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
   
    // Override point for customization after application launch.

    // Add the tab bar controller's view to the window and display.
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];

    return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
     */
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    /*
     Called as part of  transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
     */
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}


- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
}


#pragma mark -
#pragma mark UITabBarControllerDelegate methods

/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
}
*/

/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
}
*/


#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
}


- (void)dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
}

@end

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


@interface FirstViewController : UIViewController {
      UIButton *dis;
}

@property (nonatomic, retain) IBOutlet UIButton *dis;

-(IBAction) display:(id) sender;

@end

FirstViewController.m
@implementation FirstViewController
@synthesize dis;

-(IBAction) display:(id) sender{
      [[[[[self tabBarController] viewControllers] objectAtIndex:0] tabBarItem] setEnabled:false];
}

SecondViewController.h
@interface SecondViewController : UIViewController {
      UIButton *dis2;
}

@property (nonatomic, retain) IBOutlet UIButton *dis2;

-(IBAction) diss:(id) sender;

@end

SecondViewController.m
@implementation SecondViewController
@synthesize dis2;

-(IBAction) diss:(id) sender{
      [[[[[self tabBarController] viewControllers] objectAtIndex:0] tabBarItem] setEnabled:true];
}







This is the effect that i want kind of but instead of disabling the button i want it to show another view like we talked about.  FirstAViewController
0
 
LVL 2

Expert Comment

by:tisaksen
ID: 33648645
I don't think you can use UITabBarController for this. Looks like it limits your options.. You need to set the delegate of the actual tabbar to be your AppDelegate object. Otherwise you wont be able to handle didSelect:item
0
 

Author Comment

by:BTMExpert
ID: 33648774
AppDelegate.h
#import <UIKit/UIKit.h>

@interface DisDatTestAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
    UIWindow *window;
    UITabBarController *tabBarController;
      UITabBar *tabBar;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) IBOutlet UITabBar *tabBar;

@end

AppDelegate.m
#import "DisDatTestAppDelegate.h"


@implementation DisDatTestAppDelegate

@synthesize window;
@synthesize tabBarController;
@synthesize tabBar;


-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
      switch(item.tag)
      {
            case 0:
                  // first item
                  // display the view you want the first time
                  //YourViewController *ctrl = .........;
                  // addSubview or whatever you use to display it (might be a navigationController, I dont know)
            break;
            case 1:
                  // second item
            break;
            case 2:
                  // third item
                  // let's say this is the one which presents your view with a button,
                  // that when clicked, should replace the first item on the tabbar
                  // in the replace tabbar item code, set the tag of the new item to some far out value, like 9999 or whatever
                  // ie: UITabBarItem *newItem = [[UITabBarItem alloc] initWithTitle:@"Title" image:someImageObject tag:9999];
            break;
            case 9999:
                  // display the different view when the user clicks the first item on the tab bar
                  //DifferentViewForFirstTabBarItem *differentView = .....
                  // addSubview or whatever you use to display it (might be a navigationController, I dont know)
                  // if you need to replace the first tab bar item again remember to set it's tag to 0 this time.
            break;
           
            // .........
      }
}
#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
   
    // Override point for customization after application launch.

    // Add the tab bar controller's view to the window and display.
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];

    return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
     */
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    /*
     Called as part of  transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
     */
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}


- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
}


#pragma mark -
#pragma mark UITabBarControllerDelegate methods

/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
}
*/

/*
// Optional UITabBarControllerDelegate method.
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
}
*/


#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
}


- (void)dealloc {
    [tabBarController release];
    [window release];
    [super dealloc];
}

@end

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


@interface FirstViewController : UIViewController {
      IBOutlet UIButton *dis;
}

@property (nonatomic, retain) UIButton *dis;

-(IBAction) disable:(id)sender;

@end

FirstViewController.m
#import "FirstViewController.h"
#import "DisDatTestAppDelegate.h"

@implementation FirstViewController

@synthesize dis;

-(IBAction) disable:(id)sender {
      UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Test" message:@"Test" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
      
      [alert show];
      [alert release];
      
      /*UIImage* anImage = [UIImage imageNamed:@""];
      UITabBarItem *newItem = [[UITabBarItem alloc] initWithTitle:@"Title" image:anImage tag:0];
      
      NSMutableArray* newArray = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
      
      [newArray replaceObjectAtIndex:0 withObject:newItem];
      
      [self.tabBarController setViewControllers:newArray animated:YES];*/
      
      UIImage* anImage = [UIImage imageNamed:@""];
      UITabBarItem *newItem = [[UITabBarItem alloc] initWithTitle:@"Title" image:anImage tag:0];
      // create a mutable array with the tab bar items
      NSMutableArray *barItems = [NSMutableArray arrayWithArray:self.tabBar.items];
      // replace item, you must figure out the index of the object,
      // typically you would use item.tag when you replace the item when it is clicked but
      // otherwise you'll have to find a way to identify it's position in the array to be able to replace it.
      [barItems replaceObjectAtIndex:0 withObject:newItem];
      // set the new item list
      //[self.tabBarController setViewControllers:barItems animated:YES];
      // don't leak
      [newItem release];
      [anImage release];
      
}




/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
*/

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
      // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
      
      // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
      // Release any retained subviews of the main view.
      // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [super dealloc];
}

@end
0

Featured Post

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

626 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question