3
votes

So i wanted to build a tabbar that has more than 5 items and is scrollable and found this article. Easy done by subclassing the UITabBarController and hide the existing tabbar:

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

Then i just add a UIScrollView and throw some buttons in there based on the items-collection of the tabbarcontroller.

int i = 0;
for (UITabBarItem *item in self.tabBar.items)
{
    UIView *tab = [[[UIView alloc] initWithFrame:CGRectMake(i*60, 0, 60, 60)] autorelease];

    UIButton *btn = [[[UIButton alloc] initWithFrame:CGRectMake(7.5, 1, 45, 45)] autorelease];
    [btn setImage:item.image forState:UIControlStateNormal];
    btn.tag = i;
    [btn addTarget:self action:@selector(didSelectTabrBarItem:) forControlEvents:UIControlEventTouchUpInside];
    [tab addSubview:btn];

    [self.scrollView addSubview:tab];
    i++;

    if(self.selectedViewController == nil)
        [self setSelectedIndex:0];
}

I am overriding the setSelectedindex/ViewController since i need some addition drawing.

-(void)setSelectedViewController:(UIViewController *)selectedViewController
{
    [super setSelectedViewController:selectedViewController];
    [self startTimer];
}

-(void)setSelectedIndex:(NSUInteger)selectedIndex
{
    [super setSelectedIndex:selectedIndex];
    [self startTimer];
}

The problem is that when I am pressing button number 5, 6 or 7, the tabbarcontroller opens the More view. How do i get rid of that and make the last three items act like the other ones? - Could it be the call to the super?

My guess would be to completely kill the UITabBarController and implement my own custom tabbar. But is it possible to disable the more menu and have the UITabBarController select item 5, 6 and 7 as normal?

4
If you have more than 5 views a TabBar controller might not be the best navigation for your application. You should try making a list application like the Settings App in the iPhone or the Mint iPhone App. Perhaps a springboard-like navigation would be a good fit as well.rjgonzo
Springboard-esque navigation only works when the user has configured where everything is. Otherwise it takes so much longer than scanning a list.Mark Adams
Another menu style is not an option.esbenr

4 Answers

6
votes

So, since I'm too lousy to write a completely new tab bar i decided to investigate and try to hack UITabBarController.

And here's the solution:

The actual problem is that when you touch a tab bar item with index above 4, the UITabBarController vil actually display the moreNavigationController. This is a UINavigationController containing a view of type UIMoreViewControllerList, which is a type from the private Cocoa framework together with an instance of the ViewController you selected.

So how do we get rid of the More button?

Simply remove the UIMoreViewControllerList from the moreNavigationController collection, leaving only the ViewController you selected.

-(void)setSelectedViewController:(UIViewController *)selectedViewController
{
    [super setSelectedViewController:selectedViewController];

    if([self.moreNavigationController.viewControllers count] > 1)
    {        
        //Modify the view stack to remove the More view
        self.moreNavigationController.viewControllers = [[[NSArray alloc] initWithObjects:self.moreNavigationController.visibleViewController, nil] autorelease];
    }
}

Well that leaves us with a Edit button in the top right corner (Titlebar).

How do you get rid of that, then?

Yeah. Thats another dirty hack. To remove the Edit button I'd actually have to implement one method from the UINavigationControllerDelegate for the moreNavigationController on my custom UITabBarController.

//navigationController delegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{

    if ([navigationController isKindOfClass:NSClassFromString(@"UIMoreNavigationController")])
    {     
        // We don't need Edit button in More screen.
        UINavigationBar *morenavbar = navigationController.navigationBar;
        UINavigationItem *morenavitem = morenavbar.topItem;
        morenavitem.rightBarButtonItem = nil;
    }
}

And thats the way to kill off the default More functionality. I really think Apple pissed their own pants here creating a UITabBarController that both handles logic and UI stuff. Why not create a controller that has the logic to preload the ViewControllers and switch between then, and then an implementation you can use if you want the More thingie. - Or even better: Make it possible to disable the More functionality.

1
votes

I should finalize this thread. I have been having the stuff above in a App Store for a year and it has caused massive problems in the long run. It works, but it quirks when you rely on the built in features of UITabbarcontroller as it messes around with the view stack.

After going around this hot ash for over a year we decided to build our own tabbarcontroller/menucontroller. Thta took like a day and have freed us from all the fixes and quirks. My hack works, but I recommend building your own navigation class - it will pay off in the long run :-)

0
votes

I had a similar problem and solved it by using a UITabBarController and hiding the tab bar. Then I drew a custom tab bar over the top of it and when a button for a tab was clicked, call

tabbar.selectedIndex = index 

Where 'tabbar' is the original UITabBarController. Setting the selectedIndex property of a UITabBarController changes the currently displayed view controller to the controller at that index. This way you still get all the functionality of a UITabBarController but you can have as many tabs as you want and customize it however you want.

Otherwise, I don't think there is a way to remove the "more" functionality.