ios仿微博个人首页

来源:互联网 发布:大数据信息化调研提纲 编辑:程序博客网 时间:2024/04/28 01:34

前言

最近在公司拿到了一个仿微博个人主页效果的需求,于是在网上找了一个类似的demo。当时是直接拿来用的,之后空闲下来了,就研究了实现方法。于是写了这份笔记

分析

首先我们看看这个效果图
演示gif

有以下几个特点:

  • 整个页面是可以滚动的
  • 当分页栏到达顶部时,分页栏固定在导航栏下方
  • 只有当分页栏固定在顶部时,才显示导航栏
  • 状态栏的颜色会改变
  • 分页栏切换后,仍然保持之前的状态
    • 切换需要分为标题栏固定和未固定分析,这部分的效果自己看看微博的效果吧。或者直接看例子,我代码里也写下了注释了

实现步骤

一、隐藏状态栏

隐藏其实就是把导航条的背景设置为透明,于是我们可以在以下这两个方法隐藏状态栏和恢复导航条的样式

- (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;}

三、改变状态栏的颜色

这一块,具体的大家可以参考这篇http://www.jianshu.com/p/ee1c9c91a477。而在这里,我们需要注意的是,在导航控制器包裹下的控制器是不能决定状态栏的颜色的。也就是说以下这句话不起效

– (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的偏移量。

最后

以上有些细节实在不好说明,大家可以看看实现代码。里面有详细的注释。

以上是我参考http://www.jianshu.com/p/5ef0d579aea3这篇文章总结出来的。实现方法有些许不同,例如我没有把每个UITableViewController都继承同一个基类。在实际用途上,这个页面的控制器肯定是其他界面的复用。如果按照原作者的实现方法,每个继承基类的控制器都会默认留空上部分用作占位,这样的话,在其他界面显示时又要做特殊处理。此外,还添加了详细的注释,简化了一些实现方法等。若有bug请留言,希望可以帮到大家

2016-11-09Bug修复

一、增加了基类控制器

最后发现还是需要用到继承,原来的做法会把原来的子控制器tableView的代理覆盖掉,这样子控制器就不能自己监听自己的操作了,例如点击事件。

二、修复了子tableview不足以滚动的bug

0 0
原创粉丝点击