How can I use different multiple categories for UIToolbar's?
I have a few UIToolbars throughout my app. I want each one to have a different background. Here is an example of a Category I have:
#import "UIToolbar+NavBarAdditions.h"
@implementation UIToolbar (Addition)
- (void) drawRect:(CGRect)rect {
UIImage *barI开发者_如何学JAVAmage = [UIImage imageNamed:@"rowbg.png"];
[barImage drawInRect:rect];
}
@end
I have a few images rowbg1, rowbg2 etc etc that I want to use for other UIToolbars that are inside of my app. How can I choose which category to use for the respective toolbar?
Change a toolbar background
Using a subclass
A category changes all UIToolbar classes. If you need different toolbars, let each client be in charge of setting the image:
@interface UIBgToolbar : UIToolbar {
@private
UIImage *_background;
}
@end
@implementation UIBgToolbar
- (id)initWithFrame:(CGRect)aRect imagen:(UIImage*)image {
if (self = [super initWithFrame:aRect]){
_background = [image retain];
}
return self;
}
- (void) drawRect:(CGRect)rect {
UIImage *barImage = _background;
[barImage drawInRect:rect];
}
-(void)dealloc {
[_background release];
[super dealloc];
}
@end
Usage:
UIImage *bg = [UIImage imageNamed:@"bar_bottom.png"];
// 416 = 480 - status bar (20) - navigation bar (44)
CGRect rect = CGRectMake(0, 416-bg.size.height, bg.size.width, bg.size.height);
UIBgToolbar *toolbar = [[UIBgToolbar alloc] initWithFrame:rect imagen:bg];
[self.view addSubview:toolbar];
[toolbar release];
Using a subview
This is an alternative way that adds a subview and doesn't need subclasses or categories:
UIImage *bg = [UIImage imageNamed:@"bar_bottom.png"];
// 416 = 480 - status bar (20) - navigation bar (44)
CGRect rect = CGRectMake(0, 416-bg.size.height, bg.size.width, bg.size.height);
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:rect];
UIImageView *background = [[[UIImageView alloc] initWithImage:bg] autorelease];
background.frame = toolbar.bounds;
background.autoresizingMask = UIViewAutoresizingFlexibleWidth;
BOOL isIOS5 = [[[UIDevice currentDevice] systemVersion] intValue] >= 5;
toolbar insertSubview:background atIndex: (isIOS5 ? 1 : 0)];
[self.view addSubview:toolbar];
[toolbar release];
Making the background transparent.
Don't use this unless you really need a transparent background.
@interface UITransparentToolBar : UIToolbar
@end
@implementation UITransparentToolBar
- (void)drawRect:(CGRect)rect {
[[UIColor clearColor] set];
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
}
@end
Usage:
// create the toolbar
UIImage *bg = [UIImage imageNamed:@"bar_bottom.png"];
// 416 = 480 - status bar (20) - navigation bar (44)
CGRect rect = CGRectMake(0, 416-bg.size.height, bg.size.width, bg.size.height);
UIBgToolbar *toolbar = [[UIBgToolbar alloc] initWithFrame:rect];
// add the background
// self.backgroundColor = [UIColor clearColor];
UIImageView *background = [[UIImageView alloc] initWithImage:bg];
background.frame = toolbar.bounds;
background.autoresizingMask = UIViewAutoresizingFlexibleWidth;
BOOL isIOS5 = [[[UIDevice currentDevice] systemVersion] intValue] >= 5;
[toolbar insertSubview:background atIndex: (isIOS5 ? 1 : 0)];
[self.view addSubview:toolbar];
[toolbar release];
Change a navigation bar
Navigation bar background
Use Noah's code in a category.
Using a subclass is also possible:
- Create a
UINavigationToolbar
subclass containing the drawRect method from Noah's answer. - Select your MainWindow.XIB, select "Navigation Bar", press ⌥⌘3 to (show Identity Inspector), and change the class to the class you just created. - Also while in IB, press ⌥⌘4 (show Attributes Inspector) and set a number in the field Tag. If you look at Noah's code, that number decides which image to use.
Navigation bar toolbar background
Same thing as for a normal toolbar but using a category because the navigation toolbar is read-only:
// UIToolbar.h
@interface UIToolbar (Transparency)
- (void)drawRect:(CGRect)rect;
@end
// UIToolbar.m
#import "TransparentToolbar.h"
@implementation UIToolbar (Transparency)
- (void)drawRect:(CGRect)rect {
[[UIColor clearColor] set];
CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
}
@end
Usage:
// bar_bottom_bumped.png is a toolbar image with transparency
UIImage *bg = [UIImage imageNamed:@"bar_bottom_bumped.png"];
UIImageView *background = [[UIImageView alloc] initWithImage:bg];
background.frame = self.navigationController.toolbar.bounds;
background.autoresizingMask = UIViewAutoresizingFlexibleWidth;
BOOL isIOS5 = [[[UIDevice currentDevice] systemVersion] intValue] >= 5;
self.navigationController.toolbar.backgroundColor = [UIColor clearColor];
[self.navigationController.toolbar insertSubview:background atIndex: (isIOS5 ? 1 : 0)];
If you’re creating the toolbars yourself—in IB or through code—then Jano’s solution is mostly right, though I disagree with the idea of making it transparent: you should avoid doing unnecessary blending. If you need to replace the toolbars created by a navigation controller, though, you do need to use a category rather than subclassing. You can use your existing implementation; you just need to set a different tag
on each of the toolbars you want to have a different appearance, then check that value in your -drawRect:
. In other words, your view controller should have something like this:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIToolbar *toolbar = self.navigationController.toolbar;
toolbar.tag = 3; // different value for each controller, or however you want to choose the toolbar
[toolbar setNeedsDisplay];
}
and your toolbar category should have something like this:
- (void)drawRect:(CGRect)r
{
UIImage *barImage = nil;
switch(self.tag)
{
case 1:
barImage = [UIImage imageNamed:@"rowbg.png"];
break;
case 3:
barImage = [UIImage imageNamed:@"something else.png"];
break;
}
[barImage drawInRect:self.bounds];
}
You should use subclassing instead of categories.
精彩评论