一、导航控制器出栈
1、initWithRootViewController本质
UIViewController *vc = [[OneViewController alloc] init];
// 创建导航控制器
// 导航控制器必须要有一个根控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
// 会调用push方法
// initWithRootViewController底层其实是调用导航控制器的push方法,把vc成为导航控制器的子控制器
// 一旦把一个控制器压入到栈,就会把这个控制器的view添加到导航控制器的view上
// [nav pushViewController:vc animated:YES];
2、回到上个控制器或者根控制器
// 回到上一个控制器
- (IBAction)back2Pre:(id)sender {
// 导航控制器中做界面之间的跳转必须拿到导航控制器
[self.navigationController popViewControllerAnimated:YES];
// 调用pop方法并不会马上销毁当前控制器
}
// 回到根控制器
- (IBAction)back2Root:(id)sender {
// [self.navigationController popToRootViewControllerAnimated:YES];
// 还有一种方法:指定回到哪个控制器
// popToViewController使用注意点,传入进去的控制器必须是导航控制器栈里面的控制器
[self.navigationController popToViewController:self.navigationController.childViewControllers[0] animated:YES];
}
二、设置导航条内容
1、UINavigationItem:是一个模型,决定导航条的内容(左边内容,中间,右边内容)
2、UIBarButtonItem:是一个模型,决定导航条上按钮的内容
只要看到item,通常都是苹果提供的模型,只要改模型就能修改苹果的某些控件.
// 1、设置导航条的标题
self.navigationItem.title = @"chg";
self.navigationItem.titleView = [UIButton buttonWithType:UIButtonTypeContactAdd];
// 2、设置导航条左边的内容
UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithTitle:@"abc" style:UIBarButtonItemStyleDone target:self action:@selector(leftClick)];
self.navigationItem.leftBarButtonItem = leftItem;
// 3、设置导航条右边的内容
// 在iOS7之后,默认会把导航条上的按钮的图片渲染成蓝色.
// 不想要渲染导航条上的按钮的图片颜色
UIImage *image = [UIImage imageNamed:@"navigationbar_friendsearch"];
// 告诉苹果哪个图片不要渲染
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// UIBarButtonItem
UIBarButtonItem *rigthItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleDone target:nil action:nil];
// 创建按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
// 正常
[btn setBackgroundImage:[UIImage imageNamed:@"navigationbar_friendsearch"] forState:UIControlStateNormal];
// 高亮
[btn setBackgroundImage:[UIImage imageNamed:@"navigationbar_friendsearch_highlighted"] forState:UIControlStateHighlighted];
// 导航条上的子控件位置不需要我们管理,只需要管理尺寸
btn.frame = CGRectMake(0, 2000, 30, 30);
UIBarButtonItem *rigthItem1 = [[UIBarButtonItem alloc] initWithCustomView:btn];
// self.navigationItem.rightBarButtonItem = rigthItem;
// 可添加多个
self.navigationItem.rightBarButtonItems = @[rigthItem,rigthItem1];
三、控制器的View的生命周期
// 监听控制器的view的生命周期方法
// 控制器的view的生命周期方法都是以view开头
// 控制器的view即将显示的时候调用
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"%s",__func__);
}
// 控制器的view完全显示的时候调用
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"%s",__func__);
}
// 控制器的view即将消失的时候调
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
NSLog(@"%s",__func__);
}
// 控制器的view完全消失的时候调
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
NSLog(@"%s",__func__);
}
// 控制器的view即将布局子控件的时候调用
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
NSLog(@"%s",__func__);
}
// 控制器的view布局子控件完成的时候调用
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
NSLog(@"%s",__func__);
}
// 当控制器的view加载完成的时候调用
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%s",__func__);
}
执行顺序: viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear -> viewWillDisappear -> viewDidDisappear
在非ARC中经常使用
// Unload:卸载这个view
- (void)viewWillUnload
{
[super viewWillUnload];
}
// 表示控制器的view卸载完成
- (void)viewDidUnload
{
[super viewDidUnload];
// 清空界面上的数据
self.datas = nil;
}
清空界面原理:
- (void)setDatas:(NSMutableArray *)datas
{
if (_datas != datas) {
_datas = [datas retain];
[datas release];
}
}
四、微博个人详情页
大致的功能如上,导航条和文字的透明度随着移动而变化,粉红色视图有悬浮效果,并且鲨鱼图片随着滚动等比缩放,始终与粉红色视图紧挨在一起
1、搭建框架
首先拖一个Navigation Controller
设置这个控制器的根控制器为右边的View Controller
那么现在主要精力放在View Controller上
首先最底部是View Controller的view
view上面有Table View、粉红色的视图、最上面的头部视图
头部视图上面有鲨鱼图片和鸣人图片
注意:Table View必须铺满整个View Controller的view 【在代码中设置上面的额外滚动高度为(粉红色的视图的高度+最上面的头部视图的高度)】
具体结构图如下:
2、实现代码如下:
1 #import "ViewController.h"
2 // 1.项目结构:导航控制器,导航控制器上添加一个个人详情控制器
3 // 2.分析个人详情页的结构
4 // 2.1 tableView(尺寸跟控制器尺寸一样大)
5 // 2.2 头部视图不能是tableView的头部视图 + 粉红色的选项卡视图不能是tabelView的头部视图
6 // 2.3 tableView的头部视图没有悬停效果,tableView分组的头部视图才有悬停效果
7
8 #import "UIImage+Image.h"
9
10 @interface ViewController ()<UITableViewDelegate>
11 @property (weak, nonatomic) IBOutlet UITableView *tableView;
12
13 // 记录一开始lastOffsetY
14 @property (nonatomic, assign) CGFloat lastOffsetY;
15
16 //@property (weak, nonatomic) IBOutlet NSLayoutConstraint *headYCons;
17 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *headHCons;
18
19
20 @property (nonatomic, weak) UILabel *label;
21
22 @end
23
24 #define XMGHeadH 200
25 #define XMGHeadMinH 64
26 #define XMGTabBarH 44
27
28 @implementation ViewController
29
30 - (void)viewDidLoad {
31 [super viewDidLoad];
32 // Do any additional setup after loading the view, typically from a nib.
33
34 // 在iOS7之后,导航控制器下的所有UIScrollView默认顶部都会添加64的额外滚动区域.
35 // 不需要添加额外的滚动区域
36 self.automaticallyAdjustsScrollViewInsets = NO;
37
38 // 一开始y轴滚动区域是-244.
39 _lastOffsetY = - (XMGHeadH + XMGTabBarH);
40
41 // 设置tableView顶部的额外的滚动区域(选项卡的高度 + 头部视图的高度)
42 self.tableView.contentInset = UIEdgeInsetsMake(XMGHeadH + XMGTabBarH, 0, 0, 0);
43
44 // 清空导航条的背景
45 // 如何快速的清空导航条背景图片,直接传入一个空图片的UIImage对象
46 [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];
47 // 清空阴影图片
48 [self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
49
50 // 设置导航条标题
51 UILabel *label = [[UILabel alloc] init];
52
53 _label = label;
54
55 label.textColor = [UIColor colorWithWhite:1 alpha:0];
56
57 label.text = @"chg的个人主页";
58
59 // 自动计算当前label文字尺寸,并且设置控件的尺寸和文字尺寸一样.
60 [label sizeToFit];
61
62 self.navigationItem.titleView = label;
63
64 }
65 // 返回tableView有多少行
66 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
67 {
68 return 20;
69 }
70
71 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
72 {
73 static NSString *ID = @"cell";
74
75 // 从缓存池中获取cell
76 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
77
78 if (cell == nil) {
79 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
80 cell.backgroundColor = [UIColor redColor];
81 }
82
83 cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
84
85 return cell;
86 }
87
88 #pragma mark - 监听tableView滚动
89 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
90 {
91 // 获取当前滚动的偏移量值contentOffset
92 CGFloat offsetY = scrollView.contentOffset.y;
93
94
95 // contentOffset:tableView可视范围顶点与内容开始点的偏移量,内容开始点的contentOffset = 0;
96
97 // 计算下用户相对最开始偏移量滚动的多少
98 CGFloat delta = offsetY - _lastOffsetY;
99
100 // 移动头部视图
101 // 当往上移动的时候,头部视图需要往上移动,高度值需要减少
102 CGFloat headH = XMGHeadH - delta;
103
104 // 如果小于最小高度,就不在减少了
105 if (headH < XMGHeadMinH) {
106 headH = XMGHeadMinH;
107 }
108
109 _headHCons.constant = headH;
110
111 // 处理导航条
112 // 获取当前透明度,当用户移动136的时候透明度刚好为1,delta就是用户移动的距离.
113 CGFloat alpha = delta / (XMGHeadH - XMGHeadMinH) * 1;
114
115 if (alpha > 1) {
116 alpha = 0.99;
117 }
118
119 // 描述颜色
120 UIColor *color = [UIColor colorWithWhite:1 alpha:alpha];
121
122 // 设置导航条背景图片的透明度
123 [self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:color] forBarMetrics:UIBarMetricsDefault];
124
125 // 设置文字的透明度
126 _label.textColor = [UIColor colorWithWhite:0 alpha:alpha];
127 }
128
129 @end
这里的headHCons是头部视图的约束高度。
3.根据颜色生成一张1*1的相同颜色图片
UIImage+Image.h
#import <UIKit/UIKit.h>
@interface UIImage (Image)
// 根据颜色生成一张尺寸为1*1的相同颜色图片
+ (UIImage *)imageWithColor:(UIColor *)color;
@end
UIImage+Image.m
#import "UIImage+Image.h"
@implementation UIImage (Image)
+ (UIImage *)imageWithColor:(UIColor *)color
{
// 描述矩形
CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
// 开启位图上下文
UIGraphicsBeginImageContext(rect.size);
// 获取位图上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// 使用color演示填充上下文
CGContextSetFillColorWithColor(context, [color CGColor]);
// 渲染上下文
CGContextFillRect(context, rect);
// 从上下文中获取图片
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
return theImage;
}
@end
到这里功能基本也就实现了