Tag Archives: iphone

Custom colored UITabBar icons – an update

In a previous blogpost, which is still one of my most popular ones, I gave a method on how to create a tabBar with complete custom icons. It’s really more like a hack. But so far I haven’t found anything better yet. My method didn’t use any private API’s, and I have already succesfully submitted two apps in the App Store: Kust Afvalgids and Cultuurmarkt. The former one suffers from a little inconvenience: when you touch a given icon on your tabBar, you can still see the sort of “transparent” area covering the location of the icon, to indicate that this icon is active. You can get rid of that though. Here’s how.

A custom UITabBarItem implementation

To get rid of the annoying active state of an icon, all you have to do is implement your own class which inherits from UITabBarItem, and override the different icons. Then in the code you can create an instance of your custom UITabBarItem class, and assign it to the tabBarItem of your controller. Here’s how I implemented the subclass:

// CustomTabBarItem.h
@interface CustomTabBarItem : UITabBarItem {
    UIImage *customHighlightedImage;
    UIImage *customStdImage;
}

@property (nonatomic, retain) UIImage *customHighlightedImage;
@property (nonatomic, retain) UIImage *customStdImage;

@end
// CustomTabBarItem.m
#import "CustomTabBarItem.h"

@implementation CustomTabBarItem

@synthesize customHighlightedImage;
@synthesize customStdImage;

- (void) dealloc
{
    [customHighlightedImage release]; customHighlightedImage=nil;
    [customStdImage release]; customStdImage=nil;
    [super dealloc];
}

-(UIImage *) selectedImage
{
    //return self.customHighlightedImage;
    return nil;
}

-(UIImage *) unselectedImage
{
    //return self.customStdImage;
    return nil;
}

@end

Two methods need to be overridden: selectedImage, which returns the icon you want to display in the active state; and unselectedImage, which returns the icon you want to display in the inactive state. As you can see in my code, I simply return nil. This indicates that I have no icons for both active & normal state. If you’ve read my previous blog post, you know I have just created different background images for the tabBar. Each background image already has the different images in it, so I don’t need separate icons for tabBarItems. If you do work like that, you just return the correct images in the correct methods (the parts which are commented out).

Now in each sub-controller of your tabBar, you make an instance of the CustomTabBarItem class, and assign it to self.tabBarItem. Example:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    CustomTabBarItem *tabItem = [[CustomTabBarItem alloc] initWithTitle:@"" image:nil tag:0];

    //tabItem.customHighlightedImage=[UIImage imageNamed:@"icon_active.png"];
    //tabItem.customStdImage=[UIImage imageNamed:@"icon_inactive.png"];

    self.tabBarItem=tabItem;
    [tabItem release];
    tabItem=nil;
}

Again, I provided sample code to show you how to specify the different images. Each time your view will appear, your tabBarItem will be set to your custom implementation. There is still one (little) problem: If you tap a selected tabBarItem twice, the active state will show. If you have a view transition, like a flip view animation, the active state will show. I have not found a way around this yet. I guess it’s somewhere in the internals of cocoa and I have no clue how to solve it. If you do find a solution, please let me know via the comments.

Conclusion

In my latest iPhone app, I have used the system of my previous blogpost to display different background images for the tabBar per controller. Then I have combined this with a custom tabBarItem implementation to get rid of the highlight state by returning nil for selectedImage & unselectedImage. If you don’t mind that this isn’t totally bug free, then this method is a good solution I think. Apps get approved with this code, since you don’t call any private API methods.

Update – For those of you who want to see an example of the two methods combined, here’s a piece of code:

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

    [self setCustomTabBarItem];

	for(UIView *view in self.tabBarController.tabBar.subviews) {
		if([view isKindOfClass:[UIImageView class]]) {
			[view removeFromSuperview];
		}
	}

    UIImageView *imgView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"custom_tabbar_image1.png"]] autorelease];
    imgView.frame = CGRectMake(imgView.frame.origin.x, imgView.frame.origin.y - 2.0, imgView.frame.size.width, imgView.frame.size.height);
	[self.tabBarController.tabBar insertSubview:imgView atIndex:0];
}

- (void)setCustomTabBarItem
{
    // Remove highlight from tabbar item:
    CustomTabBarItem *tabItem = [[CustomTabBarItem alloc] initWithTitle:@"" image:nil tag:0];

    self.tabBarItem=tabItem;
    [tabItem release];
    tabItem=nil;
}

Custom colored UITabBar icons

On the iPhone, there is no such thing as a menu. When you create an application, you will usually work with a drill-down structure called NavigationController, or with the TabBarController. The difference between them is that the NavigationController ties screens together with increasing granular information, and the TabBarController lets you switch between screens which aren’t really connected to each other. It’s about that TabBarController I want to write this blog post about. Or rather, about a “missing feature” in it.

The TabBarController can be customized with either custom titles, custom icons or both. If you want custom icons, you will see that even though you created them in different colors, the iPhone SDK will always render them in blue when active, and in grey when inactive. Wouldn’t it be nice if you could have them in any color you’d like? I know designers would like that. More often than not, they design these pieces of the UI without remembering that in the end these icons will be blue/grey. But unfortunately there is no obvious way of achieving this. But when means are limited, creativity can help you solve many issues.

Custom colored icons

There is a trick to make your designer happy, and give him his colored icons. However, it still is a work around, and the method isn’t very stylish. It comes down to this:

  • Don’t give icons or titles to your different UITabBarItems
  • On each view of the UITabBar, set a different images as tabbar
  • Each different image has both the TabBar background in it, as well as all the icons. But the currently active page icon should be highlighted

Here are some examples:

  • background_calendar.png
  • background_clock.png
  • background_location.png
  • background_lightbulb.png

I have four tabs, so this means I need four different backgrounds for my UITabBar. On each view, I first need to remove the current background, and then I just add the background for current screen. In each ViewController I add the following:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
	for(UIView *view in self.tabBarController.tabBar.subviews) {
		if([view isKindOfClass:[UIImageView class]]) {
			[view removeFromSuperview];
		}
	}

	[self.tabBarController.tabBar insertSubview:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background_location.png"]] autorelease] atIndex:0];
}

When you don’t remove the subviews, and just try to insert your background image at index 0, then your image won’t swap. Hence we need to remove the existing subview first, and then later insert our new one. If you now build and run your application, you should see the tabbar, and if you hit each tabbar icon, you will see that the correct one is activated. And all in color!

Update 14 Sept. 2011: I wrote a follow-up blogpost here: http://blog.theanalogguy.be/2011/09/14/custom-colored-uitabbar-icons-an-update/

Custom background for UINavigationBar

When you’re working on an iphone app, more often than not, you’ll be working with the standard SDK elements and then customize those. For a recent project, I had to work with a navigation controller. And of course, the UINavigationBar needed to be customized with a proper image.

Now I had never done this before, and as usual when I don’t know how to do some task, I look in one of my two books. If the answer isn’t there, then Google comes to the rescue. So to customize the background of a UINavigationBar wouldn’t be too much of a problem I thought. And indeed it wasn’t, but I first implemented a wrong solution:

How to do it incorrectly

In the viewWillAppear:(BOOL)animated method of the ViewController, I wrote this:

[self.navigationController.navigationBar insertSubview:[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"title_bar.png"]] autorelease] atIndex:0];

Basically, it inserts an image with filename “title_bar.png” as a subView into the UINavigationBar. This works fine. In fact, I couldn’t see anything wrong with it. So I went ahead, and added it elsewhere in the code too.

So if this works, what is wrong with it? The behavior is unpredictable. In my title bar, I set the title of the current view, and I added a button on the right hand side. Sometimes the button wouldn’t render, sometimes the title wouldn’t render. Sometimes the behavior was correct only after I went to another view, and then came back to this one. So to keep it short: it is unpredictable, and you don’t want to do it this way.

How to do it correctly

To make this work, you don’t have to write a lot of code. All you need to do is subclass the UINavigationBar class, and implement the drawRect method yourself. This will override the default behavior with what you implement. So each time drawRect is called, we just make sure the “title_bar.png” image is added:

@implementation UINavigationBar (CustomImage)
- (void)drawRect:(CGRect)rect {
	UIImage *image = [UIImage imageNamed: @"title_bar.png"];
	[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
@end

The drawRect method is automatically invoked when the UINavigationBar will be rendered. Each time this happens, the image will now be automatically drawn in the title bar. Beware though, this is for all UINavigationBar’s in your project.

Book review: iPhone SDK Development

When you want to learn developing applications for the iPhone, you have to start somewhere. For me, I usually start with buying a book, and study from it. This book from the Pragmatic Bookshelf looked promising and is now my first iPhone development book. But did it get me to where I wanted to get? My review will tell you just what this book did for me.

Review

To be honest, this wasn’t my first book from the Pragmatic Bookshelf. I’ve bought The Pragmatic Programmer, and read it from cover to cover. It provided me great insights, so I hoped that this iPhone SDK Development would be of the same high quality. My goals were quite simple: I knew nothing about iPhone development, and I wanted to learn it. No, let me rephrase that: I knew nothing about iPhone development, and I wanted to learn it from this book alone, because I would be studying during my holiday in Italy, far away from the internets.

The book starts with some must-read chapters about the very basics of iPhone development. The other chapters are there for when you need them. You probably only want to read up on using MapKit, if you need it, not because it’s the basics of all iPhone applications. In this way, the chapters are well organized: basics first, fancy features later.

The first few chapters (1-7) give you a lot of information about the basics of Objective C and the iPhone SDK essentials. Since I have a programming background, I had no problem understanding these concepts, except maybe memory management. In these first chapters, the author takes you by the hand, and creates a couple of sample applications, with all code provided in the book. You just have to type it over, so to speak, and it works. Further in the book, the authors don’t go through all the trouble again and again, and then only explain the chapter’s subject in detail, leaving the rest to you.

In the book, UI elements are never created via the code. Everything is explained with the Interface Builder, a built-in tool of Xcode. This appeared to be a good choice. It saved me as a beginner from the intricacies of creating a UI element from scratch in the code. The authors teach you how to access UI elements from the got to get the data in or out of them, which is all you need in the beginning. All styling and graphical changes can be done through the Interface Builder.

When you finally reach the more advanced topics (chapters 8 through 29), you probably have spent a good amount of hours poking around in Xcode. As such, you’ve by now learned from both the book and your mistakes. I haven’t read through all the chapters just yet, only a couple I needed. From my experience, these advanced chapters give you the basics to get started with the topic. If you need more details or other functionality, you really need to get on the Internet. Not only to find answers to potential questions, but also because sometimes code is provided on the book’s website. This made it more difficult for me to study offline, which was really too bad. I spent quite some time figuring out my mistakes when dealing with Core Data.

Conclusion

iPhone SDK Development provided a very good start for me. Chapters 1-7 provided me with the basics, and chapters 8-29 provided me with information I could fall back on, if I needed to know more about that particular subject. I would recommend this book to anyone who wants to start with iPhone development, even though the book is based on SDK version 3.x. This book is aimed towards beginners, and as such delivers a good introduction.