首页"/>
ios仿微博个人首页
前言
最近在公司拿到了一个仿微博个人主页效果的需求,于是在网上找了一个类似的demo。当时是直接拿来用的,之后空闲下来了,就研究了实现方法。于是写了这份笔记
分析
首先我们看看这个效果图
有以下几个特点:
- 整个页面是可以滚动的
- 当分页栏到达顶部时,分页栏固定在导航栏下方
- 只有当分页栏固定在顶部时,才显示导航栏
- 状态栏的颜色会改变
- 分页栏切换后,仍然保持之前的状态
- 切换需要分为标题栏固定和未固定分析,这部分的效果自己看看微博的效果吧。或者直接看例子,我代码里也写下了注释了
实现步骤
一、隐藏状态栏
隐藏其实就是把导航条的背景设置为透明,于是我们可以在以下这两个方法隐藏状态栏和恢复导航条的样式
- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];// 设置导航栏背景为透明[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];// 隐藏导航栏底部黑线self.navigationController.navigationBar.shadowImage = [UIImage new];
}- (void)viewWillDisappear:(BOOL)animated {[super viewWillDisappear:animated];// 当都设置为nil的时候,导航栏会使用默认的样式,即还原导航栏样式[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];self.navigationController.navigationBar.shadowImage = nil;
}
二、导航栏的显示
其实这里导航栏的显示其实是一个假象,这里显示的导航栏是添加在UIViewController上的View,只是刚好显示在原来导航栏上的位置
- (void)setupNavigationView
{self.navigationController.navigationBar.tintColor = [UIColor whiteColor];UIView *navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 64)];navigationView.backgroundColor = [UIColor whiteColor];UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 32, kScreenWidth, 20)];titleLabel.text = @"Maple";titleLabel.font = [UIFont systemFontOfSize:17];titleLabel.textAlignment = NSTextAlignmentCenter;[navigationView addSubview:titleLabel];navigationView.alpha = 0;[self.view addSubview:navigationView];self.navigationView = navigationView;
}
三、改变状态栏的颜色
这一块,具体的大家可以参考这篇。而在这里,我们需要注意的是,在导航控制器包裹下的控制器是不能决定状态栏的颜色的。也就是说以下这句话不起效
– (UIStatusBarStyle)preferredStatusBarStyle
为此我们需要重写导航控制器的下来方法
-(UIStatusBarStyle)preferredStatusBarStyle
{return UIStatusBarStyleLightContent;
}- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
四、分页栏滚定与固定
显而易见,为了让分页栏可以滚动,我们需要将分页栏添加在可滚动的tableview中。为了让分页栏固定,我们需要将分页栏添加在不可滚动的view中。于是,整个结构就定下来了,UIViewController包裹HeaderView和3个UITableViewController。每一个UITableViewController控制一个tableview,都是UIViewController的子控制器。
1、分页栏未固定
每个tableView都添加空白tableHeaderView占位,然后再将分页栏添加在tableView上。然后再设置UIViewController为其代理,监听其滚动。
2、分页栏固定
当tableview的偏移量达到“临界值”时,将分页栏添加在UIViewController上。
- (void)scrollViewDidScroll:(UITableView *)scrollView
{CGFloat offY = scrollView.contentOffset.y;// 分页栏到达顶部时,固定分页栏if (offY > kHeaderTopHeight - kTopBarHeight){if(self.headerView.superview != self.view){self.fixed = YES;// 固定headerView[self.view insertSubview:self.headerView belowSubview:self.navigationView];CGRect rect = self.headerView.frame;rect.origin.y = kTopBarHeight - kHeaderTopHeight;self.headerView.frame = rect;}}else{if(![self.headerView.superview isEqual:scrollView]){self.fixed = NO;// 还原headerView[scrollView addSubview:self.headerView];CGRect rect = self.headerView.frame;rect.origin.y = 0;self.headerView.frame = rect;}}// 控制导航条的显示if (offY > 0) {CGFloat alpha = offY / (kHeaderTopHeight - kTopBarHeight);self.navigationView.alpha = alpha;if (alpha > 0.6 && !self.isBlack) {self.navigationController.navigationBar.tintColor = [UIColor blackColor];self.black = YES;[self setNeedsStatusBarAppearanceUpdate];} else if (alpha <= 0.6 && self.isBlack) {self.black = NO;self.navigationController.navigationBar.tintColor = [UIColor whiteColor];[self setNeedsStatusBarAppearanceUpdate];}} else {self.navigationView.alpha = 0;self.black = NO;self.navigationController.navigationBar.tintColor = [UIColor whiteColor];[self setNeedsStatusBarAppearanceUpdate];}
}
五、分页栏切换
这里我们需要用一个字典保存每一个tableView的偏移量。在显示的时候,再根据当前分页栏的情况设置每个tableView的偏移量。
最后
以上有些细节实在不好说明,大家可以看看实现代码。里面有详细的注释。
以上是我参考。实现方法有些许不同,例如我没有把每个UITableViewController都继承同一个基类。在实际用途上,这个页面的控制器肯定是其他界面的复用。如果按照原作者的实现方法,每个继承基类的控制器都会默认留空上部分用作占位,这样的话,在其他界面显示时又要做特殊处理。此外,还添加了详细的注释,简化了一些实现方法等。若有bug请留言,希望可以帮到大家
2016-11-09Bug修复
一、增加了基类控制器
最后发现还是需要用到继承,原来的做法会把原来的子控制器tableView的代理覆盖掉,这样子控制器就不能自己监听自己的操作了,例如点击事件。
二、修复了子tableview不足以滚动的bug
更多推荐
ios仿微博个人首页
发布评论