一,设置UINavigationController一些属性
1.
UINavigationBar *NaviBar = [UINavigationBar appearance];
//设置导航栏底色
//[NaviBar setBackgroundColor:UIColorWithRGBA(100, 15, 120, 0.9)];
NSDictionary *dict = @{NSFontAttributeName : [UIFont fontWithName:@"AlNile-Bold" size:22],NSForegroundColorAttributeName:UIColorWithRGB(217, 108, 0)};
//设置导航栏字体颜色,大小
[NaviBar setTitleTextAttributes:dict];
//[NaviBar setBackgroundColor:UIColorWithRGBA(100, 15, 120, 0.9)];
NSDictionary *dict = @{NSFontAttributeName : [UIFont fontWithName:@"AlNile-Bold" size:22],NSForegroundColorAttributeName:UIColorWithRGB(217, 108, 0)};
//设置导航栏字体颜色,大小
[NaviBar setTitleTextAttributes:dict];
//隐藏掉导航栏底部的那条线
NaviBar.shadowImage=[[UIImage alloc]init];
2.UIBarButtonItem 的学习,改变navigation title的字体大小、颜色,阴影。。。
有时侯你并不想把导航条左侧按钮外观字体或背景全部用以下代码来更改
UIBarButtonItem *rightItem = [YBarButtonItem barButtonWithStyle:YBarButtonStyleRoundedRectangle
Title:@"Save"
Action:@selector(saveButtonClicked)
Delegate:self];
self.navigationItem.leftBarButtonItem = rightItem;
这里就有个方法可以进行全局或局部的修改:
iOS5提供了一个比较强大的工具UIAppearance,可以轻松的统一你的界面,它提供如下两个方法:
+ (id)appearance
+ (id)appearanceWhenContainedIn:(Class <>)ContainerClass,...
第一个方法是统一全部改,比如你设置UINavBar的tintColor,你可以这样写:[[UINavigationBar appearance] setTintColor:myColor];
第二个方法是当出现在某个类的出现时候才会改变:例如:
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], [UIPopoverController class], nil] setTintColor:myPopoverNavBarColor];
(1).修改背景:
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:leftButton
forState:0
barMetrics:UIBarMetricsDefault];
(2).修改字体,阴影,字体颜色
NSDictionary* textAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
BAR_BUTTON_TITLE_TEXT_COLOR,UITextAttributeTextColor,
BAR_BUTTON_TITLE_FONT,UITextAttributeFont,
BAR_BUTTON_TITLE_SHADOW_COLOR,UITextAttributeTextShadowColor,
[NSValue valueWithCGSize:CGSizeMake(1, 1)],UITextAttributeTextShadowOffset,
nil];
[[UIBarButtonItem appearance] setTitleTextAttributes:textAttributes forState:0];
(3),修改UIBarButtonItem中文字的位置:
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(2, -1)
forBarMetrics:UIBarMetricsDefault];
二,导航条渐变出现
//
已经开始滚动
去监听滚动
,
使导航栏颜色变化
- ( void )scrollViewDidScroll:( UIScrollView *)scrollView{
[ self . navigationController . navigationBar setBackgroundImage :[ self imageWithBgColor : UIColorWithRGBA ( 25 , 24 , 24 , self .collectionView.contentOffset.y / 100 )] forBarMetrics : UIBarMetricsDefault ];
UILabel *lable=[[ UILabel alloc ] initWithFrame : CGRectMake ( 0 , 0 , 100 , 30 )];
if ( self . collectionView . contentOffset . y > 58 ) {
lable. font = [ UIFont fontWithName : @"AlNile-Bold" size : 22 ];
lable. alpha = 0 ;
lable. textColor = UIColorWithRGB ( 255 , 255 , 255 );
lable. textAlignment = NSTextAlignmentCenter ;
self . navigationItem . titleView = lable;
lable. text = self . cityName ;
}
else {
self . navigationItem . titleView = nil ;
}
- ( void )scrollViewDidScroll:( UIScrollView *)scrollView{
[ self . navigationController . navigationBar setBackgroundImage :[ self imageWithBgColor : UIColorWithRGBA ( 25 , 24 , 24 , self .collectionView.contentOffset.y / 100 )] forBarMetrics : UIBarMetricsDefault ];
UILabel *lable=[[ UILabel alloc ] initWithFrame : CGRectMake ( 0 , 0 , 100 , 30 )];
if ( self . collectionView . contentOffset . y > 58 ) {
lable. font = [ UIFont fontWithName : @"AlNile-Bold" size : 22 ];
lable. alpha = 0 ;
lable. textColor = UIColorWithRGB ( 255 , 255 , 255 );
lable. textAlignment = NSTextAlignmentCenter ;
self . navigationItem . titleView = lable;
lable. text = self . cityName ;
}
else {
self . navigationItem . titleView = nil ;
}
}
- (
UIImage
*)imageColor:(
UIColor
*)color
{
// 描述矩形
CGRect rect= CGRectMake ( 0 , 0 , 1 , 1 );
// 开启位图上下文
UIGraphicsBeginImageContext (rect. size );
// 获取位图上下文
CGContextRef context= UIGraphicsGetCurrentContext ();
// 填充上下文
CGContextSetFillColorWithColor (context, [color CGColor ]);
// 渲染上下文
CGContextFillRect (context, rect);
// 获取图片
UIImage *lastimage= UIGraphicsGetImageFromCurrentImageContext ();
// 完成 并结束上下文
UIGraphicsEndImageContext ();
return lastimage;
{
// 描述矩形
CGRect rect= CGRectMake ( 0 , 0 , 1 , 1 );
// 开启位图上下文
UIGraphicsBeginImageContext (rect. size );
// 获取位图上下文
CGContextRef context= UIGraphicsGetCurrentContext ();
// 填充上下文
CGContextSetFillColorWithColor (context, [color CGColor ]);
// 渲染上下文
CGContextFillRect (context, rect);
// 获取图片
UIImage *lastimage= UIGraphicsGetImageFromCurrentImageContext ();
// 完成 并结束上下文
UIGraphicsEndImageContext ();
return lastimage;
}
三,UINavigationController实际应用
#import <Foundation/Foundation.h>
@protocol UINavigationController <NSObject>
栈 :FILO
队列 :FIFO
UINavigationController 继承于 UIViewController ,以栈的方式管理所控制的视图控制器,至少要有一个被管理的视图控制器。
创建的时候需要用户提供一个视图控制器作为导航控制器的一个根视图控制器。
根视图控制器 : 第一个进去的控制器
self .window.rootViewController window 的根视图控制器是这个导航控制器
视图控制器切换常用方法 , 切换控制器 , 同时切换控制器显示的视图
pushViewController:animated // 进入下一个视图控制器
popViewControllerAnimated // 返回上一个视图控制器
popToViewController:animated // 返回到指定的视图控制器
popToRootViewControllerAnimated // 返回到根视图控制器
1. 创建基类 BaseViewController.h
@interface BaseViewController : UIViewController
//readonly 只有 getter 方法 , 没有 setter 方法 ,_contentLabel 自己出不来
@property ( nonatomic , retain , readonly ) UILabel *contentLabel;
@property ( nonatomic , retain , readonly ) UIButton *submitButton;
- ( void )handleSibmitAction:(UIButton *)sender; // 对应按钮响应方法
@end
2. "BaseViewController.h"
@implementation BaseViewController
// 创建实例变量
@synthesize contentLabel = _contentLabel;
@synthesize submitButton = _submitButton;
- (UILabel *)contentLabel{
if (!_contentLabel) {
// 没有 setter 方法 , 没有内部 retain, 不能加 autorelease, 保存对象的地址 , 在 dealloc 中 release, 这里引用计数需 +1
_contentLabel = [[UILabel alloc] initWithFrame: self .view.bounds];
_contentLabel.backgroundColor = [UIColor colorWithRed:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha: 1 ];
_contentLabel.textColor = [UIColor whiteColor];
_contentLabel.textAlignment = NSTextAlignmentCenter;
_contentLabel.font = [UIFont boldSystemFontOfSize: 100 ];
_contentLabel.adjustsFontSizeToFitWidth = YES ;
// 如果创建对象时先 getter button,lable 就会遮挡 button
//[self.view addSubview:_contentLabel];
// 保证 lable 永远在最下面
[ self .view insertSubview:_contentLabel atIndex: 0 ];
}
return _contentLabel;
}
- (UIButton *)submitButton{
if (!_submitButton) {
// 引用计数 +1
_submitButton = [[UIButton buttonWithType:UIButtonTypeSystem] retain];
_submitButton.frame = CGRectMake( 60 , CGRectGetHeight( self .view.bounds) - 80 , CGRectGetWidth( self .view.bounds) - 120 , 40 );
_submitButton.backgroundColor = [UIColor redColor];
[_submitButton setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal];
[_submitButton addTarget: self action: @selector (handleSibmitAction:) forControlEvents:UIControlEventTouchUpInside];
[ self .view addSubview:_submitButton];
}
return _submitButton;
}
- ( void )handleSibmitAction:(UIButton *)sender{
}
-( void )dealloc{
[_contentLabel release];
[_submitButton release];
[ super dealloc];
}
3. 创建基类 BaseViewController 的子类 RootViewController
RootViewController.m 中
//getter 出 lable 和 button, 如果不用 getter, 则这个视图控制器没有 lable 和 button, 和一般视图控制器一样
- ( void )viewDidLoad{
[ super viewDidLoad];
[ self .submitButton setTitle: @" 切换到下一个视图 " forState:UIControlStateNormal];
self .contentLabel.text = @" 根视图控制器 " ;
}
4. AppDelegate.m
RootViewController *rootVC = [[RootViewController alloc] init];
// 创建导航控制器 , 以 rootVC 为根视图控制器
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:rootVC];
// 将导航控制器指定为 window 的根视图控制器
self .window.rootViewController = navi;
[rootVC release];
[navi release];
5. 继续子类化 BaseViewController, DetailViewController
DetailViewController.m 中
- ( void )viewDidLoad{
[ super viewDidLoad];
[ self .submitButton setTitle: @" 下一级视图控制器 " forState:UIControlStateNormal];
self .contentLabel.text = @" 详情视图控制器 " ;
}
- ( void )handleSibmitAction:(UIButton *)sender{
// 将当前显示的视图控制器出栈撤销
//[self.navigationController popViewControllerAnimated:YES];
// 视图控制器一旦被入栈显示 , 就会交由导航控制器管理 ( 获取所有权 ). 本质原理是 : 视图控制器会被保存在导航控制器对应的 viewControllers 数组中
NSLog( @"%@" , self .navigationController.viewControllers);
//[self.navigationController popToViewController:self.navigationController.viewControllers.firstObject animated:YES];
// 回到根视图控制器
[ self .navigationController popToRootViewControllerAnimated: YES ];
}
6. 在导航控制器的一个根视图控制器 RootViewController 中 , 实现在这个视图上实现的 button 的方法 , 及按一下 , 切换到 DetailViewController 控制器 , 同时切换控制器显示的视图
- ( void )handleSibmitAction:(UIButton *)sender{
// 创建下一级视图控制器对象
DetailViewController *detailVC = [[DetailViewController alloc] init];
//push 入栈显示新的视图控制器 , 被导航控制器管理 ,retain+1, 如果 back 后被推回去 , 自动 deallco,pop 后引用计数 -1
// 被导航控制器管理 , 可获取其导航控制器
//push 后 detailVC 进入 navigationController 的 viewControllers 数组栈中 , 相当于 UIView 中的 subviews, 数组销毁 , 里面的引用计数全部 -1
[ self .navigationController pushViewController:detailVC animated: YES ];
[detailVC release];
}
7. 导航栏 ( 各个视图控制器的导航栏 ) 改标题 , 左右上角的按钮等
在 "DetailViewController.m" 中
// 为导航栏添加标题 , 下一个视图的左上角 <back 的名字也变成标题名字
self .navigationItem.title = @" 根视图控制器 " ;
// 如果想要下一级返回按钮只显示向左的箭头 , 则将上一级标题设置为空字符串
self .navigationItem.title = @"" ;
// 每一个视图控制器都有一个 navigationItem 属性 , 该属性是通过懒加载创建的对象 , 若果当前导航栏需要显示标题或者按钮 , 对应的视图控制器只需要给 navigationItem 的相关属性赋值即可
UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake( 0 , 0 , 300 , 40 )];
lable.textAlignment = NSTextAlignmentCenter;
lable.text = @" 根视图控制器 " ;
// NSLog(@"%@", [UIFont familyNames]);
NSLog( @"%@" ,[UIFont fontNamesForFamilyName: @"Wawati SC" ]);
lable.font = [UIFont fontWithName: @"DFWaWaSC-W5" size: 20 ];
self .navigationItem.titleView = lable;
[lable release];
// 创建 UIBarButtonItem 类的实例 , 为导航条提供按钮功能
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRewind target: nil action: nil ];
self .navigationItem.rightBarButtonItem = rightBarButton;
[rightBarButton release];
// 自定义右上角 customButton
"customButton.m" 中
- ( void )drawRect:(CGRect)rect{
CGFloat w = CGRectGetWidth( self .bounds);
// CGFloat h = CGRectGetHeight(self.bounds);
UIBezierPath *beizerPath = [UIBezierPath bezierPath];
[beizerPath moveToPoint:CGPointMake(w, 0 )];
[beizerPath addLineToPoint:CGPointMake( 0 , w / 2 )];
[beizerPath addLineToPoint:CGPointMake(w / 2 , w / 2 )];
[beizerPath addLineToPoint:CGPointMake(w / 2 , w)];
[beizerPath closePath];
[[UIColor blueColor] set];
[beizerPath fill];
}
在 "DetailViewController.m" 中
customButton *button = [customButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake( 10 , 10 , 30 , 30 );
button.showsTouchWhenHighlighted = YES ;
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:button];
self .navigationItem.rightBarButtonItem = rightBarButton;
[rightBarButton release];
< 1 > @interface UIViewController (UINavigationControllerItem)
@property (nonatomic,readonly,retain) UINavigationItem *navigationItem; // Created on-demand so that a view controller may customize its navigation appearance.
< 2 > @interface UINavigationItem : NSObject <NSCoding>
@property (nonatomic,copy) NSString *title; // Title when topmost on the stack. default is nil
@property (nonatomic,retain) UIBarButtonItem *backBarButtonItem; // 返回按钮
@property (nonatomic,retain) UIView *titleView; // Custom view to use in lieu 代替 of a title. May be sized horizontally. Only used when item is topmost on the stack. 只要是继承于 UIView 的子类都可加在状态栏 (lable,button..)
@property (nonatomic,copy) NSString *prompt; // Explanatory text to display above the navigation bar buttons. 解释说明 , 出现导航条会变高
@property (nonatomic,assign) BOOL hidesBackButton; // If YES, this navigation item will hide the back button when it's on top of the stack.
@property (nonatomic,copy) NSArray *leftBarButtonItems ;
@property (nonatomic,copy) NSArray *rightBarButtonItems;
@property (nonatomic,retain) UIBarButtonItem *leftBarButtonItem;
@property (nonatomic,retain) UIBarButtonItem *rightBarButtonItem;
< 3 > @interface UIBarButtonItem : UIBarItem <NSCoding>
- ( instancetype )initWithCustomView:(UIView *)customView;
- ( instancetype )initWithBarButtonSystemItem:(UIBarButtonSystemItem)systemItem target:( id )target action:( SEL )action; 等
typedef NS_ENUM (NSInteger, UIBarButtonSystemItem) {
UIBarButtonSystemItemDone,
UIBarButtonSystemItemCancel,
UIBarButtonSystemItemEdit,
UIBarButtonSystemItemSave,
UIBarButtonSystemItemAdd,
UIBarButtonSystemItemFlexibleSpace,
UIBarButtonSystemItemFixedSpace,
UIBarButtonSystemItemCompose, // 写
UIBarButtonSystemItemReply,
UIBarButtonSystemItemAction, // 分享
UIBarButtonSystemItemOrganize,
UIBarButtonSystemItemBookmarks, // 书签
UIBarButtonSystemItemSearch,
UIBarButtonSystemItemRefresh,
UIBarButtonSystemItemStop,
UIBarButtonSystemItemCamera,
UIBarButtonSystemItemTrash,
UIBarButtonSystemItemPlay,
UIBarButtonSystemItemPause, // 暂停
UIBarButtonSystemItemRewind, // 快退
UIBarButtonSystemItemFastForward, // 快进
#if __IPHONE_3_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
UIBarButtonSystemItemUndo,
UIBarButtonSystemItemRedo,
#endif
#if __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
UIBarButtonSystemItemPageCurl,
#endif
};
另外两种添加 UIBarButtonItem 方法
< 1 > 如果是在导航条一边创建多个 button ,在 4.0 里是通过 segmentcontrol 来间接实现
[java] view plaincopyprint?
UISegmentedControl *SegmentedControl = [[UISegmentedControl alloc] initWithItems:
[NSArray arrayWithObjects:
@" 开始 " ,
@" 暂停 " , nil ]];
[SegmentedControl addTarget: self action: @selector (segmentAction:)
forControlEvents:UIControlEventValueChanged];
SegmentedControl.frame = CGRectMake( 0 , 0 , 80 , 30 );
SegmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
SegmentedControl.momentary = YES ;
SegmentedControl.tintColor = [UIColor colorWithHue: 0.6 saturation: 0.33 brightness: 0.69 alpha: 0 ];
//defaultTintColor = [segmentedControl.tintColor retain]; // keep track of this for later
UIBarButtonItem *segmentBarItem = [[UIBarButtonItem alloc]
initWithCustomView:SegmentedControl];
self .navigationItem.rightBarButtonItem = segmentBarItem;
之后 通过 Action 方法判断是哪个 button 被按下
[java] view plaincopyprint?
- ( void )segmentAction:( id )sender
{
//NSLog(@"segmentAction: selected segment = %d", [sender selectedSegmentIndex]);
if ([sender selectedSegmentIndex] == 0 ) {
//[self startAll];
} else if ([sender selectedSegmentIndex] == 1 ) {
//[self stopAll];
}
}
< 2 > 在 iOS 5.0 中,导航条引入了新的方法 setLeftBarButtonItems:animated: 和 setRightBarButtonItems:animated: 来直接定义左右侧的多个 button ,方便了许多
[java] view plaincopyprint?
UIBarButtonItem *startBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPlay target: self action: @selector (startDownloadAll)];
UIBarButtonItem *pauseBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPause target: self action: @selector (stopDownloadAll)];
[ self .navigationItem setRightBarButtonItems:[NSArray arrayWithObjects: pauseBtn,startBtn, nil ]];
8. 导航条外观的改变
在 AppDelegate.m 中
RootViewController *rootVC = [[RootViewController alloc] init];
// 创建导航控制器 , 以 rootVC 为根视图控制器
UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:rootVC];
// 通过修改导航条的颜色来设置外观
//navi.navigationBar.backgroundColor = [UIColor redColor];back 为最里面的视图 , 被第二层高斯模糊特效盖住
navi.navigationBar.barTintColor = [UIColor redColor];
// 导航条的 tintColor 可以允许我们自定义系统样式按钮的颜色
navi.navigationBar.tintColor = [UIColor whiteColor];
// 关闭导航条的半透明效果 , 默认为 YES, 表示开启半透明 , 如果改为 NO, 导航条和视图由覆盖改为平铺
navi.navigationBar.translucent = YES ;
// 用于修改导航条的样式 , 一共两种默认为浅白色 , 还有一种是黑色 . 这两种样式可以同时影响状态栏的文字颜色
navi.navigationBar.barStyle = UIBarStyleBlack;
// UIBarStyleDefault = 0, 默认
// UIBarStyleBlack = 1, 导航栏为深色半透明 , 电池等颜色变为白色
// 自定义 导航条图片 一个像素 1*64(2*128)
// 为导航条不同的屏幕倒向下添加不同的图片作为背景 , 可设置镂空的
//UIBarMetricsDefault 竖向
[navi.navigationBar setBackgroundImage:[UIImage imageNamed: @"background" ] forBarMetrics:UIBarMetricsDefault];
//UIBarMetricsCompact 横向
[navi.navigationBar setBackgroundImage:[UIImage imageNamed: @"land" ] forBarMetrics:UIBarMetricsCompact];
// 讲导航控制器指定为 window 的根视图控制器
self .window.rootViewController = navi;
[rootVC release];
[navi release];
@end