Custom colors in UITabBar - iphone

Is it possible to use custom colors and background images in a UITabBar? I realize that Apple would like everyone to use the same blue and gray tab bars, but is there any way to customize this?
Second, even I were to create my own TabBar-like view controller, along with custom images, would this violate Apple's Human Interface Guidelines?

I found an answer to this at Silent Mac Design.
I implemented this way:
First make a subclass of UITabBarContoller
// CustomUITabBarController.h
#import <UIKit/UIKit.h>
#interface CustomUITabBarController: UITabBarController {
IBOutlet UITabBar *tabBar1;
}
#property(nonatomic, retain) UITabBar *tabBar1;
#end
 
// CustomUITabBarController.m
#import "CustomUITabBarController.h"
#implementation CustomUITabBarController
#synthesize tabBar1;
- (void)viewDidLoad {
[super viewDidLoad];
CGRect frame = CGRectMake(0.0, 0, self.view.bounds.size.width, 48);
UIView *v = [[UIView alloc] initWithFrame:frame];
[v setBackgroundColor:[[UIColor alloc] initWithRed:1.0
green:0.0
blue:0.0
alpha:0.1]];
[tabBar1 insertSubview:v atIndex:0];
[v release];
}
#end
And in your Nib file replace the class of your TabBar Controller with CustomUITabBarController.

FYI, from iOS 5 onwards you can customize various aspects of the UITabBar, including setting its background image using the backgroundImage property.
The new UITabBar "Customizing Appearance" properties in iOS 5 are:
backgroundImage
selectedImageTintColor
selectionIndicatorImage
tintColor
Given that Apple have introduced these methods in iOS 5, then it's possible they may be more sympathetic to attempts to customize the UITabBar for earlier OSes. This website says the Twitter app uses a custom tab bar, so that might be more reason that Apple would let such an app into the App Store, it's no guarantee though!

Use Following images ( Assuming, tabBar is having 5 Tabs as follows )
Create a new project using - "TabBar Application" template & Place following code.
Contents of AppDel.h File.
#import <UIKit/UIKit.h>
#interface cTabBarAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, retain) IBOutlet UIImageView *imgV;
#end
Contents of AppDel.m File.
#import "cTabBarAppDelegate.h"
#implementation cTabBarAppDelegate
#synthesize window=_window;
#synthesize tabBarController=_tabBarController;
#synthesize imgV = _imgV;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.tabBarController.delegate=self;
self.imgV.frame=CGRectMake(0, 425, 320, 55);
[self.tabBarController.view addSubview:self.imgV];
self.tabBarController.selectedIndex=0;
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
NSUInteger index=[[tabBarController viewControllers] indexOfObject:viewController];
switch (index) {
case 0:
self.imgV.image=[UIImage imageNamed:#"tBar1.png"];
break;
case 1:
self.imgV.image=[UIImage imageNamed:#"tBar2.png"];
break;
case 2:
self.imgV.image=[UIImage imageNamed:#"tBar3.png"];
break;
case 3:
self.imgV.image=[UIImage imageNamed:#"tBar4.png"];
break;
case 4:
self.imgV.image=[UIImage imageNamed:#"tBar5.png"];
break;
default:
break;
}
return YES;
}

At the beginning of ***ViewController.m add the following might help set background image of UITabBar.
#implementation UITabBar (CustomImage)
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed: #"background.png"];
[image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
#end

If you want to use custom colors for the icons (and not just the background) instead of the default gray and blue, do it like this: http://blog.theanalogguy.be/2010/10/06/custom-colored-uitabbar-icons/
Basically, you need to create complete tabbar images (background and icons and text) for each selected tab and set your UITabBarItems to no icon and no title and insert the image into the tabbar as an UIImageView in viewWillAppear:
And Apple won't mind since we are not using any private APIs.

Since iOS 7.0, you can use -[UIImage imageWithRenderingMode:] with UIImageRenderingModeAlwaysOriginal to preserve colors:
// Preserve the colors of the tabs.
UITabBarController *controller = (UITabBarController *)((UIWindow *)[UIApplication sharedApplication].windows[0]).rootViewController;
NSArray *onIcons = #[ #"tab1-on", #"tab2-on", #"tab3-on" ];
NSArray *offIcons = #[ #"tab1-off", #"tab2-off", #"tab3-off" ];
NSArray *items = controller.tabBar.items;
for (NSUInteger i = 0; i < items.count; ++i) {
UITabBarItem *item = items[i];
item.image = [[UIImage imageNamed:offIcons[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
item.selectedImage = [[UIImage imageNamed:onIcons[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
}
Works like a charm.

In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UITabBar appearance] setSelectedImageTintColor:[UIColor redColor]];
return YES;
}

As far as the UITabBar class is concerned, the icons in the bar are limited to the colours: blue for selected and grey for unselected. This is because the tab bar only uses the alpha value from the icons you supply to create the image on the bar.
The bar itself is limited to being black, as far as I can remember. I've not seen anything like the 'tint' property on UINavigationBar in the docs.
I guess you could go ahead and create your own tab bar style class and do what you want with it, but I have absolutely no idea how that fits in with Apple's HIG, or whether or not they'd challenge it during the review process.
In my experience, Apple reviewers only rejected my app if I didn't use THEIR UI elements according to the HIG. They might have a different view when it's your own UI elements you're playing with.

Here's the document that says we can't change pressed or selected appearance with our icons.
https://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/MobileHIG/IconsImages/IconsImages.html#//apple_ref/doc/uid/TP40006556-CH14-SW1
It's under the heading
Icons for Navigation Bars, Toolbars, and Tab Bars

Its possible without adding any subView.
In the class where you define the tab bar set the property of the
tabBarItem to ->>
UITabBarItem *tabBarItem1 = [[self.tabBar.tabBar items] objectAtIndex:0];
[tabBarItem1 setFinishedSelectedImage:[UIImage imageNamed:#"campaigns_hover.png"] withFinishedUnselectedImage:[UIImage imageNamed:#"campaigns.png"]];
Its a property of tabBarItem and u can change the default blue image to a custom image.
campaigns_hover.png is the selected custom image AND
campaigns.png is the custom image when not selected...
Enjoy the secret.. :)

The below code helps you to add custom colors with RGB values to ur tabBar.
self.tabBarController.tabBar.tintColor = [[UIColor alloc] initWithRed:0.00
green:0.62
blue:0.93
alpha:1.0];

You can do that without -insertSubview:atIndex, because a new UIView is not needed. You can apply a theme using QuartzCore on each view (UITabBar and it's subviews). So the UITabBar's background is added as I've described here.
Now we must apply the image on each UITabBarItem as it's background:
// UITabBar+CustomItem.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface UITabBar (CustomItem)
-(void)setSelectedItemBackground:(UIImage *)backgroundImage;
#end
Now the .m file:
// UITabBar+CustomItem.m
#implementation UITabBar (CustomItem)
#define kItemViewTag 445533 // <-- casual number
#define kItemViewOldTag 445599 // <-- casual number different from the above
-(void)setSelectedItemBackground:(UIImage *)backgroundImage {
UIView *oldView = [self viewWithTag:kImageViewItemTag];
oldView.layer.contents = nil; // <-- remove the previous background
oldView.tag = kItemViewOldTag; // <-- this will avoid problems
NSUInteger index = [self.items indexOfObject:self.selectedItem];
UIView *buttonView = [self.subviews objectAtIndex:index];
buttonView.tag = kItemViewTag;
buttonView.layer.contents = (id)backgroundImage.CGImage; // <-- add
// the new background
}
#end
You can also change the color of the selected images, as someone made here. But what I'm wondering is: can I change the color of the selected label? The answer is yes, as described below (the following works on ios 3.x/4.x, not iOS5+):
#implementation UITabBar (Custom)
#define kSelectedLabel 334499 // <-- casual number
-(void)changeCurrentSelectedLabelColor:(UIColor *)color {
UIView *labelOldView = [self viewWithTag:kSelectedLabel];
[labelOldView removeFromSuperview];
NSString *selectedText = self.selectedItem.title;
for(UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class])
isEqualToString:#"UITabBarButton"]) {
for(UIView *itemSubview in subview.subviews) {
if ([itemSubview isKindOfClass:[UILabel class]]) {
UILabel *itemLabel = (UILabel *)itemSubview;
if([itemLabel.text isEqualToString:selectedText]) {
UILabel *selectedLabel = [[UILabel alloc]
initWithFrame:itemLabel.bounds];
selectedLabel.text = itemLabel.text;
selectedLabel.textColor = color;
selectedLabel.font = itemLabel.font;
selectedLabel.tag = kSelectedLabel;
selectedLabel.backgroundColor = [UIColor clearColor];
[itemSubview addSubview:selectedLabel];
[selectedLabel release];
}
}
}
}
}
}
#end

Related

Delegate Being Sent To Wrong Class

I subclassed my navigation bar, making the title view clickable. When clicked, it will present another view controller. I am creating a protocol in the navigation bar, that will tell the navigation controller that the title view has been clicked. Here is how my navigation bar is defined:
NavigationBar.h:
#protocol NavigationBarDelegate;
#interface NavigationBar : UINavigationBar
{
id <NavigationBarDelegate> delegate;
BOOL _titleClicked;
}
#property (nonatomic, assign) id <NavigationBarDelegate> delegate;
#end
#protocol NavigationBarDelegate
#optional
- (void)titleButtonClicked:(BOOL)titleClicked;
#end
The delegate implements one optional method. The .m file is as follows:
NavigationBar.m:
#implementation NavigationBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_titleClicked = 0;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
self.tintColor = [UIColor colorWithRed:(111/255.f) green:(158/255.f) blue:(54/255.f) alpha:(255/255.f)];
UIImage *image = [UIImage imageNamed:#"titlelogo.png"];
UIButton *titleButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
titleButton.backgroundColor = [UIColor colorWithPatternImage:image];
[titleButton addTarget:self action:#selector(titleButton:) forControlEvents:UIControlEventTouchUpInside];
// self.navigationController.delegate = self;
[self.topItem setTitleView:titleButton];
[super drawRect:rect];
}
- (void)titleButton:(UIButton *)sender
{
_titleClicked = !_titleClicked;
[self.delegate titleButtonClicked:_titleClicked];
}
This creates a navbar with a logo and calls the titleButton method when the title button has been clicked. Everything is fine up till here and the navigation bar displays nicely.
In my RootViewController:
NavigationBar *navigationBar = [[NavigationBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 44.0f)];
navigationBar.delegate = self;
[self.navigationController setValue:navigationBar forKey:#"navigationBar"];
An implementation of titleButtonClicked is also there. When I click on the title view however, I get the following error: -[UINavigationController titleButtonClicked:]: unrecognized selector sent to instance
Why am I getting titleButtonClicked sent to UINavigationController? Is there something I need to do in my navigation controller? I am just using plain old UINavigationController. Do I need to subclass that too? If so, why?
EDIT:
Calling po self.delegate on line [self.delegate titleViewClicked:_titleClicked]; in NavigationBar.m yields the result below. How did the delegate change its type? How can I fix that?
(lldb) po self.delegate
(objc_object *) $1 = 0x07550170 <UINavigationController: 0x7550170>
As #idz said, the problem is with your:
#property (nonatomic, assign) delegete;
Don't you see that it's weird that you don't even have a:
#synthesize delegete;
That's because UINavigationBar already defines a delegate variable as idz said.
change your declaration to:
// use unsafe_unretained in ARC, not assign
#property (nonatomic, unsafe_unretained) myDelegete;
and of course
#synthesize myDelegate;
You have a clash/ambiguity between your delegate and UINavigationBar's delegate property. Rename your delegate to disambiguate them.

tabbar item image and selectedImage

I have a tab bar controller (its a tab bar based application, so tab bar is on MainWindow.xib). In this xib, I have added 4 tab bar items and I have set the image of all tab bar item. Due to this, I am facing 2 issues:
1) The image is white-colored, but when I run the application, its showing all the images on tab bar item as gray colored. How can I make it look same as is in the original image.
2) I have a selected image, that I want to add on the tab bar item which is currently selected. How should I do this???
UPDATED AFTER NICK's CODE:
Hey, in iOS 5, you will have to write following code in your app delegate for setting tab bar item selected and unselected image (the category solution will work only on 4):
if ([[[UIDevice currentDevice] systemVersion] floatValue]>4.9) {
NSString *selectedImageName,*unselectedImageName;
for (int counter = 0; counter < [self.tabBarController.tabBar.items count]; counter++) {
if (counter==0) {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
else if (counter==1) {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
.
.
else {
selectedImageName = <someImagename>;
unselectedImageName = <someImagename>;
}
UIImage *selectedImage = [UIImage imageNamed:selectedImageName];
UIImage *unselectedImage = [UIImage imageNamed:unselectedImageName];
UITabBarItem *item = [self.tabBarController.tabBar.items objectAtIndex:counter];
if ([item respondsToSelector:#selector(setFinishedSelectedImage:withFinishedUnselectedImage:)]) {
[item setFinishedSelectedImage:selectedImage withFinishedUnselectedImage:unselectedImage];
}
}
}
Add this category to your project. It will force tab bar items to use your original image as the disabled state instead of applying a grey gradient to them:
#implementation UItabBarItem (CustomUnselectedImage)
- (UIImage *)unselectedImage
{
return self.image;
}
#end
This may seem like it is using private APIs but I've seen this used multiple times on apps that were approved. It's not actually calling a private method, just overriding one.
If you need to specify different images for the selected and unselected image, your best bet is probably to use the tag property of the UITabBarItem and a switch statement, like this:
#implementation UItabBarItem (Custom)
- (UIImage *)selectedImage
{
switch (self.tag)
{
case 1:
return [UIImage imageNamed:#"tab-selected1.png"];
case 2:
return [UIImage imageNamed:#"tab-selected2.png"];
etc...
}
}
- (UIImage *)unselectedImage
{
switch (self.tag)
{
case 1:
return [UIImage imageNamed:#"tab-unselected1.png"];
case 2:
return [UIImage imageNamed:#"tab-unselected2.png"];
etc...
}
}
#end
Then in interface builder, don't bother with setting the tab bar item images as they'll just be ignored. Instead, set their tags to match up with the images you've specified in your switch statements.
Note that if you have multiple tab bars in your app, and you don't want them to all be overridden in this way, you can define these methods on a subclass of UITabBarItem instead of as a category. Then you can set the class of the tab bar items in your nib file to be your custom subclass instead of regular UITabBarItems, and only those ones will be affected.
EDIT:
Note that as of iOS 5 there is a better way of doing this using the UIAppearance APIs. This technique should still work, but who knows if Apple might start cracking down on it now that there is an officially supported approach. Better to use the new method unless you really need iOS 4 support.
Based on http://blog.theanalogguy.be/ works for me. Add the category UItabBarItem (CustomUnselectedImage) - haven't effect =(
the *.h
#interface CustomTabBarItem : UITabBarItem {
UIImage *customHighlightedImage;
UIImage *customNormalImage;
}
#property (nonatomic, retain) UIImage *customHighlightedImage;
#property (nonatomic, retain) UIImage *customNormalImage;
- (id)initWithTitle:(NSString *)title
normalImage:(UIImage *)normalImage
highlightedImage:(UIImage *)highlightedImage
tag:(NSInteger)tag;
#end
and *.m
#import "CustomTabBarItem.h"
#implementation CustomTabBarItem
#synthesize customHighlightedImage;
#synthesize customNormalImage;
- (id)initWithTitle:(NSString *)title
normalImage:(UIImage *)normalImage
highlightedImage:(UIImage *)highlightedImage
tag:(NSInteger)tag{
[self initWithTitle:title
image:nil
tag:tag];
[self setCustomNormalImage:normalImage];
[self setCustomHighlightedImage:highlightedImage];
return self;
}
- (void) dealloc
{
[customHighlightedImage release];
customHighlightedImage=nil;
[customNormalImage release];
customNormalImage=nil;
[super dealloc];
}
-(UIImage *) selectedImage
{
return self.customHighlightedImage;
}
-(UIImage *) unselectedImage
{
return self.customNormalImage;
}
#end
happy coding =]-

How do i remove the blue highlight when selection occurs in a UIPickerView

when i select a cell in my modified picker view, a blue background colour appears.
all other treads i have seen do not give me a good answer.
anyone has a solution?
pickerView.showsSelectionIndicator = NO;
Just set the UITableViewCell selectionStyle property to UITableViewCellEditingStyleNone
cell.selectionStyle = UITableViewCellEditingStyleNone;
I have add toolbar at the top of picker view and add cutom button as a sub view of toolbar and both picker view and toolbar are add as a subview of Main view so you can handle this.
I've met this one. Let's get a look at it in details. To create your custom picker view, you create your custom UIView class, e.g. :
#interface TimeAroundView : UIView
{
NSString *title;
UIImage *image;
}
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) UIImage *image;
#end
Then in your custom picker view controller you create some container, e.g. NSArray, which will get all TimeAroundView objects you want to represent in your picker view. So, for every object you must do
timeAroundViewObject.userInteractionEnabled = NO;
I think -(id)init is the best place for filling that container in, so you get something like this:
- (id)init
{
self = [super init];
if (self) {
// create the data source for this custom picker
NSMutableArray *viewArray = [[NSMutableArray alloc] init];
TimeAroundView *earlyMorningView = [[TimeAroundView alloc] initWithFrame:CGRectZero];
earlyMorningView.title = #"Early Morning";
earlyMorningView.image = [UIImage imageNamed:#"12-6AM.png"];
earlyMorningView.userInteractionEnabled = NO;
[viewArray addObject:earlyMorningView];
[earlyMorningView release];
TimeAroundView *lateMorningView = [[TimeAroundView alloc] initWithFrame:CGRectZero];
lateMorningView.title = #"Late Morning";
lateMorningView.image = [UIImage imageNamed:#"6-12AM.png"];
lateMorningView.userInteractionEnabled = NO;
[viewArray addObject:lateMorningView];
[lateMorningView release];
// .... (more of objects)
self.customPickerArray = viewArray;
[viewArray release];
}
return self;
}
And in your pickerView:viewForRow:forComponent:reusingView: you just return proper element from array.
That works for me.

Multiple custom backgrounds for UIToolbar

In order to create an absolute bottomed footer on top of a tableView I found that using UIToolbar for this and adding custom views for it worked fine.
My problem is that I already use this as a toolbar for a webview, and here with another background image than I need now.
By replacing the drawRect function in UIToolbar+addition.m I have a global toolbar for this that works fine in my webviews.
How can I expand this so that I can select which version(background) to use the different places?
My UIToolbar+addition.m:
#import "UINavigationBar+addition.h"
#implementation UIToolbar (Addition)
- (void) drawRect:(CGRect)rect {
UIImage *barImage = [UIImage imageNamed:#"toolbar-bg.png"];
[barImage drawInRect:rect];
}
#end
Try creating separate .h and .m files for each "version", and import the appropriate .h into the class file you'd like it to affect.
Why not just add a barImage property to your extension?
#interface UIToolbar (Addition)
#property (nonatomic, retain) UIImage *barImage;
#end
Then, in your implementation (I'm doing this assuming you're not using ARC. If you are, obviously remove the retain/release stuff):
#implementation UIToolbar (Addition)
#synthesize barImage = _barImage;
//Override barImage setter to force redraw if property set after already added to superView...
- (void)setBarImage:(UIImage *)barImage {
if (_barImage != barImage) {
UIImage *oldBarImage = [_barImage retain];
_barImage = [barImage retain];
[oldBarImage release];
//Let this UIToolbar instance know it needs to be redrawn in case you set/change the barImage property after already added to a superView...
[self setNeedsDisplay];
}
}
- (void) drawRect:(CGRect)rect {
[self.barImage drawInRect:rect];
}
//If you're not using ARC...
- (void)dealloc {
[barImage release];
[super dealloc];
}
#end
Now, all you have to do is set the barImage property after instantiating your UIToobar. e.g.:
UIToolBar *myToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; //Or whatever frame you want...
myToolbar.barImage = [UIImage imageNamed:#"toolbar-bg.png"];
[self.view addSubView:myToolbar];
[myToolbar release];
And, if you want to change it after it's already onscreen, you can do so by just setting the barImage property to a new UIImage.
Looks like it's been a year since this question was posted, but hopefully this might help someone.

Adding an overlay to a grid tableView

I have a tableview which each row has 4 images. I have implemented a share option which will allow the user to select multiple images. How can I add an overlay or some kind of visual effect to show that the image is selected?
I would like to add some overlay to display that an image is selected, but How would this be done without adding a new set of subview for each thumbnail? And once that is done, how would the selection of the new views be linked back to the images behind them so that they can be added to an array?
Or is there an easier way to do this?
Thanks
Depending on how you're implementing this grid view, it might make sense to track all of the selecting and deselecting at that level.
As for the overlay, the quick and dirty way is to subclass UIImageView, add a BOOL property called selected. Then you can override the setter for selected and handle showing or hiding your overlay view.
Here's how I would setup my subclass. First the interface:
#interface SelectableImageView : UIImageView
#property (nonatomic, assign, getter = isSelected) BOOL selected;
#end
and the implementation...
#interface SelectableImageView ()
#property (nonatomic, retain) UIView *overlayView;
#end
#implementation SelectableImageView
#synthesize selected;
#synthesize overlayView;
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
overlayView = [[UIView alloc] initWithFrame:frame];
overlayView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.75];
overlayView.hidden = YES;
[self addSubview:overlayView];
}
return self;
}
- (void)setSelected:(BOOL)flag
{
selected = flag;
self.overlayView.hidden = !flag;
}
- (void)dealloc
{
[overlayView release], self.overlayView = nil;
[super dealloc];
}
#end