[iOS] 列表滑动展开隐藏头部HeaderView

https://blog.csdn.net/weixin_30247159/article/details/97504894

https://blog.csdn.net/Cloudox_/article/details/70272845?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control
平常遇到大多数的带有列表的应用都会遇到这个场景:在列表顶端有一个Header,当向上滑动列表时,压缩header,向下滑动列表到头时,展开header。这种样式在例如微博,twitter这些展示动态的界面里很常见。这种效果怎么实现呢?下面介绍我用的方法。

新博客:wossoneri.com

先看一下效果图

首先看一下BiliBili客户端的视频浏览界面。默认界面Header完全展开,并且Header显示AV号(别乱想,就是视频编号了)以及播放按钮。滑动之后Header被压缩,按钮移到AV号左边。
 

 

我就照着界面简单实现了主要功能,比较简陋。对于按钮移动的动画就没有去花时间还原了,毕竟这里主要是为了实现滚动压缩、展开Header,动画不讨论。

 

实现思路

如图所示:

首先在要将该界面分成两部分:一个ScrollHeader,一个UITableView

  • ScrollHeader占据屏幕上方,高度为展开后的高度
  • UITableView占据整个屏幕,这样可以完全滚动。为了让内容不被ScrollHeader遮盖,设置contentOffset属性即可

我这里用的ScrollHeader是作为独立的控件使用,与UITableViewHeaderView并无关系

之后将ScrollHeader分成两部分:topViewbottomView

  • topView 即为压缩后的布局
  • bottomView 即为展开后的布局
    我这里采取将topView固定在ScrollHeader的顶部,覆盖在bottomView上方,根据滑动对其淡入淡出。

另一种效果是把topViewbottomView上下连接在一起,也就是没有覆盖关系,然后当bottomView向上滑时topView从屏幕外滑入屏幕内。这个读者可以尝试着实现一下。

实现方法

首先按照前面的设计将界面布局好,之后的重点是为ScrollHeader增加滑动效果。
由于我的ScrollHeader继承的是UIView,所以为了处理滑动,为其设置一个UIScrollView

@property (nonatomic, strong) UIScrollView *headerScrollView;

这个属性的作用就是获得UITableView对应的scrollView,因为UITableView本身是继承UIScrollView的,所以在初始化ScrollHeader的时候可以这么写:

 
  1. MyScrollHeader header = [[MyScrollHeader alloc] init];

  2. header.headerScrollView = _tableView;

这样,在ScrollHeader中就可以通过headerScrollView来判断滑动状态了。

剩下的工作就是捕捉滑动状态,并且对滑动距离进行计算,移动topViewbottomView了。对于计算也不做过多说明了,因为没有几张草图也说不清。直接贴上代码,跟着代码算一下就知道怎么回事了。

 
  1. #pragma mark - scroll state

  2. -(void)willMoveToSuperview:(UIView *)newSuperview{

  3. [self.headerScrollView addObserver:self forKeyPath:@"contentOffset" options:(NSKeyValueObservingOptionNew) context:Nil];

  4. self.headerScrollView.contentInset = UIEdgeInsetsMake(_bottomHeight, 0, 0, 0); // tableview 偏移

  5. }

  6.  
  7. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ //监视滑动

  8. CGPoint newOffset = [change[@"new"] CGPointValue];

  9. [self updateSubViewsWithScrollOffset:newOffset];

  10. }

  11.  
  12. -(void)updateSubViewsWithScrollOffset:(CGPoint)newOffset {

  13.  
  14. // NSLog(@"scrollview inset top:%f", self.headerScrollView.contentInset.top);

  15. // NSLog(@"new offset before:%f", newOffset.y);

  16. // NSLog(@"newOffset : %f", newOffset.y);

  17.  
  18. float startChangeOffset = - self.headerScrollView.contentInset.top;

  19.  
  20. newOffset = CGPointMake(newOffset.x, newOffset.y < startChangeOffset ? startChangeOffset : (newOffset.y > _destinaOffset ? _destinaOffset : newOffset.y));

  21. // NSLog(@"new offset after:%f", newOffset.y);

  22.  
  23. float newY = - newOffset.y - _bottomHeight;

  24. float d = _destinaOffset - startChangeOffset;

  25. float alpha = 1 - (newOffset.y - startChangeOffset) / d;

  26.  
  27. self.frame = CGRectMake(0, newY, self.frame.size.width, self.frame.size.height);

  28. topView.frame = CGRectMake(0, -newY, self.frame.size.width, self.frame.size.height);

  29.  
  30. topView.alpha = 1 - alpha;

  31. bottomView.alpha = alpha;

  32.  
  33. _currentOffset = newOffset.y;

  34. NSLog(@"current offset: %f", _currentOffset);

  35. }

最后放上源码

github

粗略写的,代码是用自动布局写的。往后抽空会优化一下代码,把ScrollHeader封装成控件方便使用。

转载于:https://www.cnblogs.com/rossoneri/p/5211647.html

相关资源:CollectionView Header 上拉下拉显隐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值