It’s been a while I haven’t written anything about iPhone :) Anyways, today I added a fancy UITabBar (like in #Tweetie 2) to one of my applications. I thought I would share the code since I saw lots of iPhone Dev folks are looking for this :)
Initially I started googling, then I ended up a StackOverflow entry says you have to Roll it :) Since my need was just placing an indicator on top of the UITabItem, I didn’t go for that way.
Here is how I did:
First, I created an UIImageView which has the indicator icon. Then I added this view to my UITabBar as subview.
UIImage *upArrow = [UIImage imageNamed:@"up-arrow.png"]; UIImageView *imageView=[[UIImageView alloc] initWithImage:upArrow]; imageView.tag = ICON_TAG; [upArrow release]; [self.tabBarController.tabBar addSubview:imageView];
This wasn’t quite enough for my need since I needed indicator to be centered. So I did some math :)
int itemCount = [self.tabBarController.tabBar.items count]; CGFloat cellWidth = tabBarController.view.frame.size.width/itemCount; CGFloat center = (cellWidth / 2) - (INDICATOR_WIDTH / 2);
Now I could easily use this center as my indicator center. However I noticed that this wasn’t enough either since I want it to move every time after I tap to the next UITabBarItem. So I did some refactoring and:
#define INDICATOR_WIDTH 10 //u can define st like this
-(void) addIndicatorTo:(int) index {
int itemCount = [self.tabBarController.tabBar.items count];
CGFloat cellWidth=tabBarController.view.frame.size.width/itemCount;
CGFloat center = (index * cellWidth) + (cellWidth / 2)
- (INDICATOR_WIDTH / 2);
UIImage *upArrow = [UIImage imageNamed:@"up-arrow.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:upArrow];
imageView.tag = ICON_TAG;
[upArrow release];
[self.tabBarController.tabBar addSubview:imageView];
}
// just listen the item index change
- (void)tabBarController:(UITabBarController *)tbController
didSelectViewController:(UIViewController *)viewController {
[self addIndicatorTo:tbController.selectedIndex];
}
So far so good. Wait a second, this adds new images every time I tap to the next UITabBarItem :S Anyways, so I refactored my code a little more:
#define INDICATOR_WIDTH 10, u can define st like this
#define INDICATOR_WIDTH 9, u can define st like this
#define ICON_TAG 11, u can define st like this
-(UIImageView *) createNewIndicator {
UIImage *upArrow = [UIImage imageNamed:@"up-arrow.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:upArrow];
imageView.tag = ICON_TAG;
[upArrow release];
return imageView;
}
-(UIImageView *) findIndicator {
// return existing one
for (UIView *view in self.tabBarController.tabBar.subviews) {
if (view.tag == ICON_TAG) {
return (UIImageView *) view;
}
}
// if not return a new one
return [self createNewIndicator];
}
-(void) addIndicatorTo:(int) index {
int itemCount = [self.tabBarController.tabBar.items count];
CGFloat cellWidth = tabBarController.view.frame.size.width / itemCount;
CGFloat center = (index * cellWidth)
+ (cellWidth / 2) - (INDICATOR_WIDTH / 2);
UIImageView *imageView = [self findIndicator];
imageView.frame = CGRectMake(
indicatorPositionX,
3 - INDICATOR_HEIGHT,
INDICATOR_WIDTH,
INDICATOR_HEIGHT
);
[self.tabBarController.tabBar addSubview:imageView];
}
This is basically it. So I did some animation too, here is the result:
If you guys need, I can upload the working source code to somewhere.. Hope this guides a bit.










Why don’t you use UITabBarController? I usually have the same effect with less work.
December 9, 2009, 5:57 AMFor 2 reasons, first saving UITabItem positions and reloading them back when application starts cause problems. You’re ending up an inconsistent layout. Second, it is a best practice to handle UITabItem selections in the application delegate if you have only one UITabBar view.
December 9, 2009, 10:03 AMI thing there is something wrong with the first piece of code: UIImage *upArrow = [UIImage imageNamed:@"up-arrow.png"]; is alreadt autorelased image (not new/alloc/copy) [upArrow release]; // it can cause a problem but *imageView is not released and should cause a leak
December 9, 2009, 8:42 PMCan you provide a source, may be the video is too small to see what the difference Thanks.
December 9, 2009, 8:43 PM@andrew, I’m not re-creating the up-arrow view every time. It’s tagging the view on first create and use it every time it moves. So it won’t cause any memory leak at that point. I’ll provide the source, u can see it there.
December 10, 2009, 12:56 AMWhere is a good place to get icons for use in my tabbars???
January 25, 2010, 10:12 AMHow bout some source code?
May 5, 2010, 12:21 PMHum, what’s “indicatorpositionX” ? THanks for the code!
June 6, 2010, 11:16 PMDo you have the source uploaded somewhere? That would be really helpful. Thanks!
June 9, 2010, 4:17 PMthis site has a very cool implementation of this http://applemaniacos.com/?p=603
July 9, 2010, 4:26 PMhello, great work !!! do you have the right to use this “tbc” instead of tabBarController and “vc” instead of “viewController” method in delegate? if so can you explain why and give me the link to the Apple documentation that confirms if you like, I can not myself find it in the documentation. Thank you
August 5, 2010, 9:53 AMWorks excellent, thanks a lot! :)
(answer to Seraphins comment if someone still wonders: indicatorPositionX is the variable incorrectly declared as “center”, so correct by changing: CGFloat center = (index * cellWidth) + (cellWidth / 2) – (INDICATOR_WIDTH / 2); to CGFloat indicatorPositionX = (index * cellWidth) + (cellWidth / 2) – (INDICATOR_WIDTH / 2); )
September 16, 2010, 1:32 PMHey,
Great post! Can you post the source code? I’d love to see it.
Thanks.
September 20, 2010, 10:07 PM