iOS 控件定制iOS高仿源码iOS学习

类似简书/微博/Twitter个人中心中多分页scollView

2017-06-12  本文已影响687人  FindCrt

背景

自以为完美的解决方案demo在此-TFMultiTabScrollView

这种界面效果需要一大段话来描述,也没有专门的名词,简单说,就是简书APP的个人简介的样式

简书样式

同样也是微博/Twitter的个人中心样式。总结下特点就是:

那么这个和网易新闻的界面有什么区别?看上去好像一样。
重点就在这个头部界面,头部上下滚动也是可以带动内容上下,而头部横向滑动却不会带动内容分页切换

我找了下目前的一些方案,发现并没有很完美的,比如嵌套UIScrollview的滑动冲突解决方案。这也是一开始我想的,似乎大家很容易走到嵌套scrollView的路线上,而这条路似乎是个死胡同。

我的方案

层级图

界面结构示例 view数据层次

这样做可以达到:

但是还有几个问题需要解决:

  1. 分页scrollView的内容会被头部遮挡一部分
  2. 横向切换分页后,新的分页头部是不是没有了?还是需要用3个头部?但是用3个是不是切换起来会很难看?
  3. 头部横向滑动时,会带动分页横向切换,这个效果是不需要的

解决:

  1. 调整分页scrollView的contentInsert.top,让顶部内容空出
  2. 这个问题是关键,当初就是想到这里而否定了,而没有走下去。解决方法就是:

整个过程里,视觉上看起来好像头部视图一直没动。这效果就达到了。而且因为头部视图又放到了当前的分页内容ScrollView上,所以之前的效果继续保持。

  1. 这是手势冲突的问题,自定义头部视图的view,然后添加一个UIPanGestureRecognizer手势,然后实现手势冲突的方法:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    
    //_tabContainer是横向滑动的scrollView
    if (otherGestureRecognizer.view == _tabContainer) {
        return NO;
    }
    
    return YES;
}

_tabContainer是横向滑动的scrollView,如果是和头部的pan手势和横向滑动ScrollView的手势冲突了,就返回NO。因为头部视图在上层,所以它的首先优先了。这样就把横向滑动的手势给屏蔽了。

这么做只是为了空白的头部视图不会触发横向内容切换,如果在头部视图加入更多控件,比如再加一个UIScrollView,它本身是可以自动屏蔽横向ScrollView(绿色)的手势的。

这样做就避开了scrollView嵌套滑动手势的问题

到这主要的问题就解决了,剩下的就是分页内容ScrollView上下滑动时,头部的悬浮问题了。

使用KVO检测分页scrollView的contentOffset,然后:

额外效果

不完美的尝试

1. 三层嵌套scrollView

这种界面结构,很容易想到的就是3个scrollView嵌套:一个大的竖向scrollView----横向分页scrollView----每个分页自身的scrollView。最外层的竖向scrollView为了是头部能够滑动,所以说这个头部才是这里的症结啊!但这种结构带来的是两个竖向的scrollView的滑动切换问题:

那么为什么不一直滑动外面的scrollView呢?这其实也是一种方案,只要把内容视图的内容完全的展开,然后只滑动外层的scrollView来切换显示内容。不好的是这样就没法使用tableView的重用功能了,比如你有很多的cell,像简书的动态那一栏。但分页是可以做的,只要加载新的内容后在继续全部展开。但这个不完美的瑕疵让人不爽。

一开始我以为scrollView的哪个滑动是hitView的问题,但后来发现scrollView的滑动是它自带的pan手势来控制滑动的。手势一旦识别了,就不会再识别,除非是新的触碰,这就是这种方案为什么要放手再重新滑动才能内外scrollView切换。

如果scrollView的滑动不是它自带的手势处理,而是一个统一的手势,而scrollView只要接受来自这个统一的手势的滑动数据就好了。这样只需要把数据的输出调整成另一个scrollView就可以完成完美的滑动切换。这里就牵扯到一点设计的问题了。

2. 模拟滚动的头部视图

这种方案是:
整体的父视图 ---- 横向的scrollView ---- 分页的竖向scrollView
整体的父视图 ----- 头部

也就是头部视图和横向的scrollView是同一个层级上,然后头部在上面覆盖。

这样要要解决的关键问题就是:头部上竖向滑动,要带动分页内容色scrollView滑动。而横向滑动啊,点击啊之类的都没有问题了,因为它已经不再嵌套scrollView的层级里了。

所以我自定义了一个头部(demo里的TFScrollSimulateView),然后给它加了pan手势来模拟scrollView的滚动,其实手指拖动是很好实现的,头部的手势拖动了多少就修改scrollView的contentOffset多少,麻烦的是:

所以我做了一个计时器,在手指离开后,不断的计算滑动的距离,而pan手势是有velocityInView:方法可以取得速度。这样其实基本可以解决问题了,但有个不完美的是scrollView减速的公式只能猜:
module -= KTimerInterval * _friction * (10000 + module * module); //阻力和速度平方成正比,速度减去a*t

但是后来在一个项目里找到了相关公式:弹簧公式

弹簧公式
3. 用图片欺骗

其实如果不需要横向滑动切换分页的效果,只能点击切换的话,这个问题的难度直线下降,因为这样就不需要横向的scrollView了,内外层的scrollView可以合成一个,就完全不存在什么嵌套的问题了。

但是如果一定要有横向切换的效果呢?可以在开始横向滑动的时候,做两张图片覆盖在内容部分。手指滑动的时候,是图片在切换,但是这个图片长得跟分页的scrollView一样,让人看起来好像是分页内容切换了一样。

这个具体没去实现,只是想法,这种欺骗眼睛的手法是挺有意思的。

2017.6.28更新


修改了问题:

  1. 分页scrollView在滑动过程中会添加新的子视图,导致遮住头部,比如UITableViewsectionHeader.
  2. _currentVisableHeaderH没有初始值导致滑动出错
  3. 分页切换时,如果频繁点击会导致界面闪烁

完善功能:

  1. 在不需要自动扩充底部内容的时候,有可能某个分页内容很少,导致头部滑动不到顶部,在切换的时候会出现“突然掉下来”的现象,现在改成动画,体验更好些。
  2. 做好了某个分页滑动,其他分页同步滑动内容的处理。能够达到从A分页离开时,如果你已经滑动到了第10行是贴着头部视图的底部的,在其他分页移动了头部视图后,A分页的内容也会跟随移动,保证回去时还是第10行贴着头部。但是这个只有在moveHeaderOnlyContentTopNO的时候有效。
上一篇 下一篇

猜你喜欢

热点阅读