-
先梳理一下层级结构
主要层级结构:
其他层级结构:
-
注意点:
开发中应该注意,基类应尽量使用UIViewController
如果需要使用UITableViewController,可以在UIViewController上加一个UITableView;
避免使用UITableViewController和UICollectionView
是因为UITableViewController和UICollectionView会限制程序的弹性空间,不便于今后的扩展
-
细节处理:
1.在控制器B上添加TableView和HeaderView后,由于iOS 7设置导航栏后,为了不影响视图展示,系统会默认帮助我们对视图进行向下偏移,参考链接:
http://www.jianshu.com/p/4cdcfb97704f
所以手动做了如下处理:
// 设置表格的间隔
tableView.contentInset = UIEdgeInsetsMake(kHeaderHeight, 0, 0, 0);
// 设置滚动指示器的间距
tableView.scrollIndicatorInsets = UIEdgeInsetsMake(kHeaderHeight, 0, 0, 0);
2.在控制器A Push到 控制器B后,设置NavigationController为隐藏状态
当返回控制器A时,应避免出现以下导航条融合的现象:
所以在控制器A中需要使用:
// [self.navigationController setNavigationBarHidden:NO]; 返回此控制器显示导航条时会融合叠加
[self.navigationController setNavigationBarHidden:NO animated:YES];
3.顶部视图缩放处理:监听偏移量,设置顶部视图高度;通过设置图片填充方式为:ScaleAspectFill,就可以忽略宽度的计算
补充:在设置图片前,手动对图片进行了优化,使图片尺寸刚好为我们UIImageView的尺寸,如果不进行处理,尺寸过大,在返回前一控制器时,就可能会出现图片超出控制器的bug,还需要对图片进行裁切处理(设置clipsToBounds为YES)
放大效果图:
4.上拉整体移动+下拉放大代码:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offSetY = scrollView.contentOffset.y + scrollView.contentInset.top;
NSLog(@"%f",offSetY);
if (offSetY > 0) {
NSLog(@"整体移动");
_headerView.h = kHeaderHeight;
_headerImageView.h = _headerView.h;
_headerView.y = - offSetY;
}else {
NSLog(@"放大");
// 调整HeaderView和HeaderImageView
_headerView.y = 0;
_headerView.h = kHeaderHeight - offSetY;
_headerImageView.h = _headerView.h;
}
}
5.按照上述监听偏移后的处理效果图:
随着不断向上滚动,顶部视图完全移出屏幕,TableView的第一行完全显示与顶部和状态栏重合
处理:
-
当视图向上滚动时,让顶部视图最大滚动距离为: 顶部视图高度-64(导航栏高度)
-
当视图向上不断滚动时,通过 1 - 偏移量/滚动最大距离计算透明度
说明:在滚动时,设置的是UIImageView的透明度,而非HeaderView的透明度
同时这里为了呈现效果更明显,给HeaderView设置了黑色背景色
当顶部视图滚动我们设定的最大距离后,顶部视图已经完全隐藏,而导航栏在Push到控制器B时也做了隐藏处理,所以这里将顶部视图做了仿导航栏的处理
1.将顶部视图HeaderView的背景色设置与导航栏颜色一致
2.给HeaderView添加一根仿导航栏的底部分割线;当顶部视图滚动放大时,需要修改分割线的Y轴坐标(或者透明度也可以)
仿导航栏的底部分割线:
- 状态栏处理:在控制器B中,顶部设置了状态栏为UIStatusBarStyleLightContent样式,当顶部视图滚动透明变化时,当到达一个临界点时,变为UIStatusBarStyleDefault样式
并且需要我们手动调用setNeedsStatusBarAppearanceUpdate方法来更新状态的变化
//1.声明一个成员变量,用来设置状态栏状态
UIStatusBarStyle _statusBarStyle;
//2.由于方法执行顺序的关系,所以将此成员变量的初始化放在了init方法中:
- (instancetype)init{
// 设置导航栏
_statusBarStyle = UIStatusBarStyleLightContent;
return [super init];
}
//3.设置状态栏
- (UIStatusBarStyle)preferredStatusBarStyle{
NSLog(@"%s",__func__);
return _statusBarStyle;
}
//4.在偏移图像放大时,设置状态栏状态,并手动更新状态
_statusBarStyle = (alpha < 0.5) ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent;
[self.navigationController setNeedsStatusBarAppearanceUpdate];
效果图: