新浪微博个人主页效果实现(头像随tableview滑动)
来源:互联网 发布:北京教育网络和信息中心 编辑:程序博客网 时间:2024/05/16 13:56
效果图
注意细节:
- 三个tableview的滚动都可以推动顶部图片和切换栏的滚动。
- 只要切换栏没有贴住导航栏,3个tableview都是从第一个cell开始显示。
- 切换栏贴住导航栏时,每个tableview的显示位置会被保持。
- 切换栏贴住导航栏,手指在当前页面拖动使切换栏脱离导航栏然后再贴住导航栏,另外2个tableview的显示状态被保持。
实现:
结构
- 研究微博个人主页容易发现这里使用了3个tableview。我在主控制器上添加3个子控制器,每一个子控制器管理一个tableview,然后将3个tableview添加到主控制器view上,所有的子控制器都继承自BaseTableViewController,方便后面的滚动监听。
- 每个tableview右边的指示条滚动范围都包含了顶部视图(图片)。在之前的版本中,我没有让tableview们共用一个顶部视图,而是给它们设置了同样的tableHeaderView(包含同样的imageView和同样的将会被切换栏覆盖的空白区域)。虽然这种结构能够实现微博个人主页的效果,但是不方便扩展,比如给tableview增加滑动手势,来左右切换要显示的界面。
- 在最新版本中,我给每个tableview都设置了240高度(图片高度200+切换栏高度40)的空白UIView作为tableHeaerView,并让3个tableview共用的一个headerView(包括要显示的图片和切换栏)。
首先将headerView加入到当前显示的tableview 上,跟着tableview滚动。当偏移量能够达到切换栏贴着导航栏时,将headerView加入到主控制器view中,固定位置;当偏移量要使切换栏脱离导航栏时,又将headerView加入到当前显示的tableview中;要切换当前显示的tableview,也需要根据偏移量来判断加入到哪个view上。
监听
我在这里采用代理方式来监听每个tableview在Y轴上的偏移量,主控制器作为BaseTableViewController的代理。 协议方法:
@protocol TableViewScrollingProtocol <NSObject>- (void)tableViewScroll:(UITableView *)tableView offsetY:(CGFloat)offsetY;- (void)tableViewWillBeginDecelerating:(UITableView *)tableView offsetY:(CGFloat)offsetY;- (void)tableViewDidEndDecelerating:(UITableView *)tableView offsetY:(CGFloat)offsetY;@end
计算
- (void)tableViewScroll:(UITableView *)tableView offsetY:(CGFloat)offsetY{ if (offsetY > headerImgHeight - topBarHeight) { if (![_headerView.superview isEqual:self.view]) { [self.view insertSubview:_headerView belowSubview:_navView]; } CGRect rect = self.headerView.frame; rect.origin.y = topBarHeight - headerImgHeight; self.headerView.frame = rect; } else { if (![_headerView.superview isEqual:tableView]) { for (UIView *view in tableView.subviews) { if ([view isKindOfClass:[UIImageView class]]) { [tableView insertSubview:_headerView belowSubview:view]; break; } } } CGRect rect = self.headerView.frame; rect.origin.y = 0; self.headerView.frame = rect; }}
这段代码主要是实时监听tableview的Y轴偏移量,如果当前offsetY大于136(图片高度200减去导航栏状态栏高度64))的话,就将headerView添加到主控器view上,此时切换栏紧贴导航栏。如果小于的话,就将headerView添加到当前显示的tableView上,跟随tableview滑动。
切换栏在没有贴住导航栏时,三个tableview的Y轴偏移量是同样的,贴住时就不再一样。 我在主控制器里设置了一个字典来存储每个tableview的偏移量,key为tableview所在控制器的地址(之前我的使用的是tableview的地址,造成的问题是在tableview上拖拽,会造成其他两个控制器view被提前加载一次)。这样我就可以随时记录和改变每个偏移量,然后在切换到要显示的tableview时,直接设置给它的contentoffset.y就可以了。
- (void)tableViewDidEndDragging:(UITableView *)tableView offsetY:(CGFloat)offsetY { _segCtrl.userInteractionEnabled = YES; NSString *addressStr = [NSString stringWithFormat:@"%p", _showingVC]; if (offsetY > headerImgHeight - topBarHeight) { [self.offsetYDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id _Nonnull obj, BOOL * _Nonnull stop) { if ([key isEqualToString:addressStr]) { _offsetYDict[key] = @(offsetY); } else if ([_offsetYDict[key] floatValue] <= headerImgHeight - topBarHeight) { _offsetYDict[key] = @(headerImgHeight - topBarHeight); } }]; } else { if (offsetY <= headerImgHeight - topBarHeight) { [self.offsetYDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id _Nonnull obj, BOOL * _Nonnull stop) { _offsetYDict[key] = @(offsetY); }]; } }}
当手指离开屏幕时,如果当前tableview没有速度了,就要在tableViewDidEndDragging:offsetY:方法里面获取tableview的偏移量。如果offsetY大于136的话,先把自己的存起来。而另外两个tableview,如果它们之前的偏移量小于等于136,现在就要改成136了(切换过去的话,让它们刚好偏移到切换栏贴住导航栏);如果offsetY小于等于136,就将三个tableview的存储偏移量设为一样。
如果当前tableview还有速度,就要在tableViewDidEndDecelerating: offsetY:方法里面设置,处理方式一样。
- (void)segmentedControlChangedValue:(HMSegmentedControl*)sender { [_showingVC.view removeFromSuperview]; BaseTableViewController *newVC = self.childViewControllers[sender.selectedSegmentIndex]; if (!newVC.view.superview) { [self.view addSubview:newVC.view]; newVC.view.frame = self.view.bounds; } NSString *nextAddressStr = [NSString stringWithFormat:@"%p", newVC]; CGFloat offsetY = [_offsetYDict[nextAddressStr] floatValue]; newVC.tableView.contentOffset = CGPointMake(0, offsetY); [self.view insertSubview:newVC.view belowSubview:self.navView]; if (offsetY <= headerImgHeight - topBarHeight) { [newVC.view addSubview:_headerView]; for (UIView *view in newVC.view.subviews) { if ([view isKindOfClass:[UIImageView class]]) { [newVC.view insertSubview:_headerView belowSubview:view]; break; } } CGRect rect = self.headerView.frame; rect.origin.y = 0; self.headerView.frame = rect; } else { [self.view insertSubview:_headerView belowSubview:_navView]; CGRect rect = self.headerView.frame; rect.origin.y = topBarHeight - headerImgHeight; self.headerView.frame = rect; } _showingVC = newVC;}
这段代码就是移除之前的tableview,添加将要显示的。 唯一注意点就是要根据偏移量来判断将headerView加到主控制器view上还是tableview上。
其它
1.关于导航栏颜色渐变的处理,我这里采用的是将系统导航栏设为无色。
- (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]; [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; self.navigationController.navigationBar.shadowImage = nil;}
然后添加一个navView(UIView)盖在导航栏上,然后滚动监听改变其alpha就好了。
2.为了记录准确的偏移量,跟微博一样,采取了在滚动过程中第一次单击切换栏使tableView停止滚动,第二次单击切换栏才切换tableView的做法。因为tableView自带了单击停止滚动的效果,所以如果切换栏没有贴住导航栏时,它的父控件headerView作为tableView的一部分,单击切换栏就可以让tableView停止。如果切换栏贴住导航栏时,它的父控件headerView就是控制器view的一部分了,我的做法是此时屏蔽掉headerView对触摸事件的响应,这样子切换栏后面的tableView部分就可以响应该单击事件了。详情请看源码,分析过程请看http://www.jianshu.com/p/2f664e71c527
3.状态栏颜色变化已经添加,gif图没有体现出来。详情请看源码,分析过程请看http://www.jianshu.com/p/ee1c9c91a477
4.研究发现新浪微博的顶部视图并没有下拉放大的效果,而是图片隐藏了一部分,下拉会显示出来。下拉放大实现起来比较容易,并且我觉得意义不大,在此就不在添加了。
Demo下载地址:https://github.com/wobangnidashui/WeiboHomepage
原文地址:http://www.jianshu.com/p/5ef0d579aea3
- 新浪微博个人主页效果实现(头像随tableview滑动)
- 新浪微博的Tab滑动效果
- 仿新浪微博的Tab滑动效果、手势滑动
- 安卓仿知乎个人主页,实现嵌套滑动和渐隐效果
- 安卓仿知乎个人主页,实现嵌套滑动和渐隐效果
- 安卓仿知乎个人主页,实现嵌套滑动和渐隐效果
- 个人主页常见的头像与背景图不同步移动的下拉效果实现
- 百度贴吧(新浪微博)个人主页效果(附带一个超轻量级可自定义的侧滑删除的layout)
- iOS开发-仿新浪博客个人主页效果
- iOS-tableview顶部拉伸效果(头像拉伸)
- iOS 实现点击微信头像效果
- 实现圆形头像效果
- [Android] PorterDuff使用实例----实现新浪微博图片下载效果
- [Android] PorterDuff使用实例----实现新浪微博图片下载效果
- [Android] PorterDuff使用实例----实现新浪微博图片下载效果
- RadioGroup实现仿新浪微博的效果
- tableView 实现隐藏效果
- 新浪微博textarea效果
- 跑马灯效果设置
- IOS设置NavigationBar颜色
- java中map集合的用法
- ubuntu设置 SSH 通过密钥登录
- oracle 没有 limit用法,但有伪列 rownum
- 新浪微博个人主页效果实现(头像随tableview滑动)
- ADO方式 连接sql server数据库报错:[DBNETLIB]无效的连接
- SOCKET原理
- 简单区间动态规划
- logback使用案例
- js实现折叠&展开
- 在Settings开发中用到的相关编译命令及编译流程
- 视频播放的基本原理
- iOS-实现UIScrollview的无限循环滑动(转载自Kenshin Cui's Blog)不过感觉快速滑动还是有缺陷啊