链接地址:http://codecloud.net/15369.html
iOS 仿nice首页的navigationbar消失显示效果(hidesBarsOnSwipe) iOS 前些天产品汪找到我,滑动着nice的首页,跟我说:“小新!能否实现像nice这样的,上滑让导航栏消失,下滑让导航栏显示”。“完全可以,一行代码的事儿”我自信的回答。因为网上一搜:怎么像safari一样滑动的时候隐藏navigation bar?都会告诉你一行代码就搞定。这一行代码就是:navigationController.hidesBarsOnSwipe = Yes当然这句代码确实可以实现这个效果,我马上让产品汪看,想显示自己的能力,结果产品汪说:“是不是状态栏没有背景?状态栏不应该是透明的”。仔细对比发现:nice的状态栏不仅有个背景,而且它们navigationBar消失的时候是从状态栏显示的时间下面经过的。直接使用navigationController.hidesBarsOnSwipe = Yes的效果图如下:iOS 仿nice首页的navigationbar消失显示效果(hidesBarsOnSwipe)nice的效果图如下:iOS 仿nice首页的navigationbar消失显示效果(hidesBarsOnSwipe)iOS 仿nice首页的navigationbar消失显示效果(hidesBarsOnSwipe)到这里是不是发现“这一行代码的事儿”有点大了。很显然这一行代码搞不定了,于是乎开始想办法给状态栏添加背景,网上有一堆资料,但对这个效果一点用都没有,如果导航栏是一直显示着,可能还可以凑合着用,但现在是…无奈之下就自己“操刀了”给状态栏添加背景:在- (void)viewWillAppear:(BOOL)animated;方法中实现:UIView *statusView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenW, 20)];statusView.backgroundColor = [UIColor whiteColor];self.statusView = statusView;[[UIApplication sharedApplication].keyWindow addSubview:self.statusView];就这样就给状态栏添加上了背景,但是这个背景会在其它控制器中依然存在,因为我们加到了keywindow上,因为nav是透明的就会出现下面的不协调显示,让人感觉不爽。iOS 仿nice首页的navigationbar消失显示效果(hidesBarsOnSwipe)有人可能会说在首页消失的我们在- (void)viewWillDisappear:(BOOL)animated;方法中将它移出就行了。对这样可以,只需:[self.statusView removeFromSuperview];即可,倘若我们不是所有控制器都需要滑动的时候隐藏navigation bar还需加上self.navigationController.hidesBarsOnSwipe = NO;并且在- (void)viewWillAppear:(BOOL)animated;中加上self.navigationController.hidesBarsOnSwipe = YES;。这样做其它控制确实不在有这样的情况了,但是首页这个不协调的显示依然在,怎么办。那就直接禁止它透明,都设成白色的背景行了,对这样是可以的,只需self.navigationController.navigationBar.translucent = YES;即可。至此我们是给状态栏添加上背景了,也实现了像safari一样滑动的时候隐藏navigation bar。但是我们没有实现navigationBar消失的时候是从状态栏显示的时间下面经过的。这只是一个细节,实在实现不了就跟经理说,也许做成这个样子就行了。但是我们要严格要求自己,这正是我们提高能力的时候。于是乎我冒出一个想法:自己写。也就有了这篇文章的高潮部分了。首先,需要搞清楚5点。1、- (void)bringSubviewToFront:(UIView )view;的使用;2、UIScrollView 的contentOffset属性的含义;3、- (CGPoint)translationInView:(nullable UIView )view;方法的使用4、为什么一定要设置self.navigationController.navigationBar.barTintColor=[UIColor whiteColor];属性5、搞清楚UIScrollView,UITableView,navigationBar的内在联系然后再去看代码。*1、- (void)bringSubviewToFront:(UIView )view;方法可以将指定的视图推送到前面,*2、UIScrollView 的contentOffset属性的含义是:scrollview当前显示区域顶点相对于frame顶点的偏移量*3、- (CGPoint)translationInView:(nullable UIView )view;获取到的是手指移动后,在相对坐标中的偏移量*4、设置self.navigationController.navigationBar.barTintColor=[UIColor whiteColor];属性的目的:一是方便修改导航栏的背景颜色,二是我们将给navigationBar添加一个UIView控件,苹果官方文档给的解释是:The behavior of tintColor for bars has changed on iOS 7.0. It no longer affects the bar’s background and behaves as described for the tintColor property added to UIView.To tint the bar’s background, please use -barTintColor.并且这个view的背景颜色跟self.navigationController.navigationBar.barTintColor是保持一致的。*5、UIScrollView,UITableView,navigationBar的内在联系:UIScrollView是UITableView的父类,而navigationBar又在UITableView上(我是这样理解的不知道是否有错),所以只要将UIScrollView的contentOffset偏移量修改即可实现此需求。其次,来看代码。自定义个NavBarViewController继承UIViewController, NavBarViewController.h文件代码如下: @interface NavBarViewController : UIViewController - (void)followSwipeScrollView:(UIView *)scrollView; @endNavBarViewController.m文件代码如下:#define NavBarFrame self.navigationController.navigationBar.frame@interface NavBarViewController ()@property (weak, nonatomic) UIView *scrollView;
@property (strong, nonatomic) UIPanGestureRecognizer *panGesture;
@property (strong, nonatomic) UIView *overLay;
@property (assign, nonatomic) BOOL isHidden;
@end
@implementation NavBarViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//设置navigationBar跟随滚动的视图(可以是scrollView或者tableview,webview。)
-(void)followSwipeScrollView:(UIView *)scrollView
{
self.scrollView = scrollView;
self.panGesture = [[UIPanGestureRecognizer alloc] init];
self.panGesture.delegate = self;
self.panGesture.minimumNumberOfTouches = 1;
[self.panGesture addTarget:self action:@selector(handlePanGesture:)];
[self.scrollView addGestureRecognizer:self.panGesture];
self.overLay = [[UIView alloc] initWithFrame:self.navigationController.navigationBar.bounds];
self.overLay.alpha = 0;
self.overLay.backgroundColor = self.navigationController.navigationBar.barTintColor;
[self.navigationController.navigationBar addSubview:self.overLay];
[self.navigationController.navigationBar bringSubviewToFront:self.overLay];
}
#pragma mark - 兼容其他手势
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
#pragma mark - 手势监听方法
-(void)handlePanGesture:(UIPanGestureRecognizer *)panGesture
{
CGPoint translation = [panGesture translationInView:[self.scrollView superview]];
//显示
if (translation.y >= 5) {
if (self.isHidden) {
self.overLay.alpha = 0;
CGRect navBarFrame = NavBarFrame;
CGRect scrollViewFrame = self.scrollView.frame;
navBarFrame.origin.y = 20;
scrollViewFrame.origin.y += 44;
scrollViewFrame.size.height -= 44;
[UIView animateWithDuration:0.5 animations:^{
NavBarFrame = navBarFrame;
self.scrollView.frame = scrollViewFrame;
if ([self.scrollView isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)self.scrollView;
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y + 44);
}else if ([self.scrollView isKindOfClass:[UIWebView class]]){
UIWebView *webView=(UIWebView *)self.scrollView;
webView.scrollView.contentOffset = CGPointMake(webView.scrollView.contentOffset.x, webView.scrollView.contentOffset.y + 44);
}
}];
self.isHidden = NO;
}
}
//隐藏
if (translation.y <= -20) {
if (!self.isHidden) {
CGRect frame = NavBarFrame;
CGRect scrollViewFrame = self.scrollView.frame;
frame.origin.y = -24;
scrollViewFrame.origin.y -= 44;
scrollViewFrame.size.height += 44;
[UIView animateWithDuration:0.2 animations:^{
NavBarFrame = frame;
self.scrollView.frame = scrollViewFrame;
if ([self.scrollView isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)self.scrollView;
//contentOffset:scrollview当前显示区域顶点相对于frame顶点的偏移量
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y-44);
}else if ([self.scrollView isKindOfClass:[UIWebView class]]){
UIWebView *webView=(UIWebView *)self.scrollView;
webView.scrollView.contentOffset = CGPointMake(webView.scrollView.contentOffset.x, webView.scrollView.contentOffset.y-44);
}
} completion:^(BOOL finished) {
self.overLay.alpha = 1;
}];
self.isHidden = YES;
}
}
}
-(void)viewDidAppear:(BOOL)animated{
[self.navigationController.navigationBar bringSubviewToFront:self.overLay];
}
@end
最后是使用说明:
1.将需要此效果的 UIViewController 继承NavBarViewController;
2.调用方法 [self followRollingScrollView:self.**]; //可以是scrollView或者tableview,webview。
注意:一定要设置 self.navigationController.navigationBar.barTintColor 属性。
(此方法的核心不是将navigationBar隐藏了,只是将UIScrollView的contentOffset:便宜量上移了,navigationBar也跟着上移了,而已)
至此,要其它需要实现像nice这样的navigationBar需求,只要继承NavBarViewController设置相关属性,实现相关方法即可。如有理解错误请多多指教,希望大家能共同进步。
dome地址:https://pan.baidu.com/s/1mhT7lLu
阅读原文