美文网首页IOSUI进价上海快风信息科技有限公司
iOS新浪新闻首页卡片滚动特效实现浅谈

iOS新浪新闻首页卡片滚动特效实现浅谈

作者: 随行的羊 | 来源:发表于2017-12-20 14:07 被阅读1830次

公司项目采用了这个特效。

Leader非常中意这个特效,说要在我们app中使用,问我能不能实现,我一看这个特效,卧槽,涉及了好多技术点,实现难度很大。如果是自己做特效还好,模仿别人的特效,做的粗糙没什么,如果要做得好,就得考虑好多细节。身为男人,怎么能说不行,自己给自己安排时间,偷偷搞,经过了几天的艰苦奋战,终于完成了,开森。
能够完成这个特效,感谢她,感谢他,感谢一如既往支持我的人。

进入正题

先看下新浪的特效(版本 v6.6.0)


新浪新闻首页卡片滚动特效

先分析一下这个滚动特效,有3种方式控制滚动:

1、1个是手指上下滑动整个表格,中间的滚动视图会跟着一起动。
2、1个是左右滑动中间的滚动视图,滚动视图会快速滑动。
3、1个是左右晃动手机,根据角度不同,滚动视图跟着一起动。

需要解决很多问题:

1、中间的滚动视图是一块一块移动的,停止时距离中间最近的卡片会自动滑动到中间,居中对齐。
2、中间的滚动视图在滑动的时候发现卡片是叠在一起的,中间的在上层,其他部分在下层,根据距离中间位置的远近来区别上下层。
3、中间的滚动视图在滑动的时候发现卡片大小不一致,中间的最大,越靠近边框越小。
4、中间的滚动视图在滑动的时候发现滑动的距离和卡片移动的距离并不是成正比,而是按照不断变化的加速度移动的。
5、中间的滚动视图滑到左右边缘时视图透明度改变。
6、循环滚动方案的实现
7、上下滑动表格时,中间的滚动视图要跟着一起滑动,上滑时向左移动,下滑时向右移动。
8、左右晃动手机时,中间的滚动视图要跟着一起滑动,向左晃动时卡片向左移动,向右晃动时卡片向右移动。
9、需要保证刚才提到的3种控制方式互不干扰。

大问题大概就是这几个,当然还有很多小问题,就不一一列出来了。

那么,说干就干

完成这个特效之前,首先是要选择实现工具,实现工具的选择很重要,相当于方向,方向选对了,才能使上大力气。
实现工具有3种:

1、自定义滚动视图
2、UIScrollView
3、UICollectionView

第一种,使用自定义滚动视图,亲自去Github上面找了不少关于自定义滚动视图的demo,觉得难度不是一般的难,而是二班的难呐,想着新浪的iOS开发水平应该也没那么强,肯定不是这种方案,就Pass了第一种。
那么看下第二种,使用UIScrollView,苹果自己弄的UIScrollView,可以分页是可以分页,但是只能整个视图分页,无法做到区域分页,看了不少的Demo,实现效果也差强人意,无奈Pass了第二种。
那么第三种呢?使用UICollectionView,在网上找到了不少可以提供灵感的Demo,感觉上是可行的,然后伟哥给了类似的Demo告诉我这种方案的可行性。可以的,那就用这种方式搞起。

确定好了方向之后就全力以赴了。

问题1:中间的滚动视图是一块一块移动的,停止时距离中间最近的卡片会自动滑动到中间,居中对齐。
UICollectionView有个布局类叫做UICollectionViewFlowLayout,可以在里面实现卡片效果,通过计算每个可见Cell到中间位置,来计算出偏移量,得出CollectionView最终停留的位置,实现自动滑动到中间,居中对齐的效果。实现以下方法:

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity

问题2:中间的滚动视图在滑动的时候发现卡片是叠在一起的,中间的在上层,其他部分在下层,根据距离中间位置的远近来区别上下层。
看UICollectionViewFlowLayout布局文件,通过计算可见Cell到中心点位置,来确定Cell的位置,达到叠加的效果。上下层的概念则是通过z轴的不同来实现,搞过游戏的朋友可能会更清楚一些,三维坐标系中有x轴,y轴,z轴,通过z轴确定视图的上下层次。实现以下方法:

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)oldBounds

问题3:中间的滚动视图在滑动的时候发现卡片大小不一致,中间的最大,越靠近边框越小。
在UICollectionViewFlowLayout布局文件中解决,设置好垂直缩放系数,根据距离的远近进行放大处理,距离中间的放到最大。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

问题4:中间的滚动视图在滑动的时候发现滑动的距离和卡片移动的距离并不是成正比,而是按照不断变化的加速度移动的。
在UICollectionViewFlowLayout布局文件中解决,根据可见Cell到中心的不同位置设置移动距离,不同的距离使用不同的加速度。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

问题5:中间的滚动视图滑到左右边缘时视图透明度改变。
在UICollectionViewFlowLayout布局文件中解决,通过计算边缘距离,来动态改变透明度。

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

问题6:循环滚动方案的实现
关于循环滚动方案,网上的说法层出不穷。我以前也搞过循环滚动,中间呈现3个,使用5个视图进行循环滚动。但这种方案计算比较复杂,功力不够的小伙伴还是不要尝试的好。还有一种方案是可以让它滚动到最后一格的时候,跳转到第一格,这种方案有点不是很流畅。最终我采用了中间定位法实现了循环滚动,需要使用下面的方法:

[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];

问题7:上下滑动表格时,中间的滚动视图要跟着一起滑动,上滑时向左移动,下滑时向右移动。
需要在表格类中滚动代理方法里面设置滚动时设置UICollectionView的ContentOffset偏移量,然后在scrollViewDidEndDragging和scrollViewDidEndDecelerating两个方法中设置滚动结束后,UICollectionView的ContentOffset偏移量,需要计算到屏幕中间位置的偏移量进行偏移。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

问题8:左右晃动手机时,中间的滚动视图要跟着一起滑动,向左晃动时卡片向左移动,向右晃动时卡片向右移动。
晃动手机,涉及到硬件支持。iPhone手机内配置了各种传感器,其中一个就是重力感应。通过了解重力感应,知道了加速器,使用加速器来控制晃动偏移量,发现效果不好,抖动特别厉害,在网上也没有特别好的例子说明。那么改用陀螺仪,苹果的陀螺仪做的非常精致,效果也很好,非常稳定,但是又发现了新问题,就是运动停止不了。最终在加速器和陀螺仪的配合之下,终于完美的解决了问题。

- (void)startGyroUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMGyroHandler)handler
- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler

问题9:需要保证刚才提到的3种控制方式互不干扰。
涉及到条件判断,不仅需要在表格的UIScrollView代理方法做控制,还要在UICollection代理方法做控制,保证效果互不干扰。

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

完成之后的效果如下:


我做的卡片滚动特效

如果是按照新浪新闻的还简单一点,但是问题是,我们的产品总是会搞点花样,比如修改透明度,修改圆角呀,等等,所以实现的难度就增加了不少。总之,兵来将挡水来土掩,完成就是了。

尾记:有人说服务端比客户端强,并非如此。闻道有先后,术业有专攻,不同的人,Level也不同。做接口考虑大数据,考虑数据库结构,查询优化等等,这些说白了无非还是工具、数学、逻辑思维、数据结构、算法,跟客户端差不多。客户端也要考虑代码框架设计、网络框架设计、数据库设计、特效空间数学计算、逻辑处理、数据结构、算法等等。客户端做的强的人,转到服务端也是分分钟搞定的事。

文末补充:

很高兴,通过我的思路,有人已经把这个特效做出来了,先不说实现代码质量的好坏,但实现了是好事。有需要的朋友可以去看看他的文章,以及他的demo,希望有更多的人向他学习,自己动手丰衣足食。

-------------------------------我是分割线-------------------------------

2017-12-20

相关文章

网友评论

  • f819d773bb62:大兄弟,给个demo吧,要被炒了哇~:sob: ,那个人写的我看了,改起来太麻烦了,或者说我不会改。。:joy:
  • SwordDevil:兄弟 demo来一份 时间太着急了 没办法自己去写了
    随行的羊:@SwordDevil 评论中有人实现了,你可以去看看。
  • 032c6843a285:小哥哥 有一个问题,有点乱。看不懂。。代码
    随行的羊:@Nslog_hsw 这个挺好理解的。
  • ZHANGMIAO_:emmm 我现在也在写这个效果 感觉挺难的呢:grin:
    随行的羊:或许你可以看下这个:https://www.jianshu.com/p/7234cb7ec429
  • Mr_Lucifer:核心代码没放出来啊, 单看文章 很难写出来. 如同 先准备鲤鱼, 再用刀处理鲤鱼, 上锅 大火, 加调料, 红烧鲤鱼完成 的感觉.
    随行的羊:@情不知所已 不是的,iCarousel效果比较差。:smiley:
    39473b4d2e11:iCarousel ?
    随行的羊:评论里面有人已经根据我的思路实现出来了,你可以思考一下。:smile: :smile: :smile:
  • 一直在跑:大神 求一个demo 我们公司最近也需要这种效果, 时间急迫,跪求
  • Yvan_deng:效果看着不错,用到时再拿出来研究下
    随行的羊:@Yvan_deng 嗯嗯,:fist: :fist: :fist:
  • 一往情深_b560:oc实现的 层叠有问题,麻烦看下
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    //获取所有cell的布局属性
    NSArray *itemArr = [super layoutAttributesForElementsInRect:rect];
    //collectionView 中心点坐标X
    CGFloat CenterX = self.collectionView.width*0.5+self.collectionView.contentOffset.x;

    CGRect visibleRect; //可视区域frame
    visibleRect.origin = self.collectionView.contentOffset;
    visibleRect.size = self.collectionView.frame.size;

    for (UICollectionViewLayoutAttributes *attrs in itemArr) {
    if (!CGRectContainsRect(visibleRect, attrs.frame)) continue;

    CGFloat space = ABS(attrs.center.x - CenterX);
    CGFloat scale = 1 + 1 - (space/(self.collectionView.width*0.5));
    attrs.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return itemArr;
    }
    随行的羊:亲,你可以看看这个:https://www.jianshu.com/p/6091c5e37289 。:smiley: :smiley: :smiley:
    一往情深_b560:层叠现象是 要么右侧的整体在左侧上面, 要么左侧整体在右侧上面
  • d88b14b33f5c:没有DEMO我咋star呢
    随行的羊:你想想看,如果你自己根据这个思路做出来了,那么不是会有很多人star你么。:smiley: :smiley: :smiley:
  • 我叫王可可:收藏一波
    随行的羊:@我叫王可可 :smile: :smile: :smile:
  • EvanJq:可以给份demo 学习下细节处理吗?
    随行的羊:书山有路勤为径。相信通过思路的讲解,自己再动手训练,应该问题不大,祝顺利。不鼓励看Demo。:smile:
  • 2690b40560b2:哈?我是谁?我在哪?我为什么在看这篇文章?🙃🙃886
    随行的羊:学开发不?iOS从入门到放弃。:joy:
  • 名扬丶四海:有没有demo?
    随行的羊:@名扬丶四海 👌🏻
    名扬丶四海:@随行的羊 thanks
    随行的羊:@名扬丶四海 你好,是有Demo的,但是比较鼓励自己去探索,这样才更有挑战性。:grin: :grin: :grin:

本文标题:iOS新浪新闻首页卡片滚动特效实现浅谈

本文链接:https://www.haomeiwen.com/subject/odbwwxtx.html