iOS那些“垃圾”的轮播

作者: xiAo__Ju | 来源:发表于2016-12-04 17:36 被阅读3520次

轮播视图通常也叫Banner,90%以上App都会用到的一个控件,网上有很多开源代码,但是至今我觉得比较好的一个是SDCycleScrollView,因为他解决了我接下来要吐槽的两个问题。

通常实现定时自动滚动Banner的思路大体有三种

  1.  3个`UIImageView`
  2.  N+2个`UIImageView`思路
  3.  N * section(个人不推荐,因为这将代码写死了,当有个无聊的人真的滚动到最后一个section时,程序就会crash了)

前两种思路又分为用UIScrollViewUICollectionView实现,个人没有用过第一种思路,都是第二种,本文也是基于第二种思路,这两种思路的中心思想其实都是运用了视觉误差

具体思路请跳转

中文
英文

快速滑动时卡顿

先来看看那些“垃圾”Banner

卡顿问题一(3个UIImageView思路)

Aiqiyi.gif Youku.gif

通过卡顿频率,我猜想这两个项目的Banner思路应该一样,用的三个UIImageView

不知道你是否看得到动图中卡顿的问题,如果你手机上恰好装了这两个App,可以自己试一下,很简单,只要快速滑动就可以复现问题。

但是这两个的PageControl还是处理得很好的,能实时滚动到相应的位置。

卡顿问题二((N+2)个UIImageView思路)

Tianmao.gif

这个问题不好看出,因为他的卡顿频率比较低,刚好是一组轮播视图的周期。必须在第N+1张时才会复现。想看得清楚的小伙伴,如果自己项目Banner是这个思路可以测试一下自己项目的。

再看看这个PageControl的位置,在你快速滑动时,它是不动的,我猜想他控制PageControl的位置应该是在这个方法里做的

   func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }

卡顿原因

就是这个两个方法其中一个里计算cell位置的判断条件不对

func scrollViewDidScroll(_ scrollView: UIScrollView) { }

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }

Tab切换卡中间,不能复位

由于这个问题比较难复现,我就用自己的Demo测试的

UICollectionView实现,会自动修复

Test.gif

UIScrollView实现,需手动修复

HalfScreen.gif

动图中应该可以清楚的看到滚动视图滚动的坐标不对。

原因

这个具体原因我也不知道,这是所有轮播都会发生的问题,我猜想是跟内部的RunLoop应该有关。

还有的Banner是pageControl和cell联动不及时,比如咸鱼

因为是在这里处理控制pageControl的位置的

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { }

简书Banner的pageControl向左手动拖动时又太灵敏。

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let page = scrollView.contentOffset.x / scrollView.frame.width
        if page <= 0.0 {
            // 向右拉
            collectionView?.scrollToItem(at: IndexPath(item: urlStrs.count - 2, section: 0), at: .centeredHorizontally, animated: false)
            pageControl?.currentPage = urlStrs.count - 3
        } else if page >= CGFloat(urlStrs.count - 1) {
            // 向左
            pageControl?.currentPage = 0
            collectionView?.scrollToItem(at: IndexPath(item: 1, section: 0), at: .centeredHorizontally, animated: false)
        } else {
            let value = page.truncatingRemainder(dividingBy: 1) < 0.5
            if value { // cell过半才改变pageControl(简书的Banner应该没有这个判断)
                pageControl?.currentPage = Int(page) - 1
            }
        }
    }

推荐

UIScrollView 实践经验 详细讲了UIScrollView,并配有Demo
LazyScrollView来至天猫团队,据说天猫首页用的这个,有复杂UI的同学可以学习下
UITableView的Cell复用原理和源码分析LazyScrollView结合起来学习,肯定有很多收获

最后附上修复以上问题的Demo

相关文章

网友评论

  • 西门欥雪:先收藏了。
  • KA_STEM:刚才楼主提到的卡顿bug。产生原因是不是楼主描述的那样呢。有没有自己验证过呢。我工程里就是第一种思路实现的。运行很流畅。没毛病
    xiAo__Ju:嗯,下来试了一下!http://www.jianshu.com/p/c716d4e0d8bb你们的方案应该和这篇文章里面demo方案一致!虽然快速滑动没有像文中说的那种卡顿,但是给人有一种延迟,并不是很跟手,你可以下载我的demo对比一下流畅度
    我文中说了,我没用过3个UIImageView的方案实现过,只是猜想,当然这样有点不负责!以后尽量做到严谨!
    KA_STEM:@xiAo__Ju 我能理财
    xiAo__Ju:@KA_STEM 你的项目叫什么,我下载一个试一下
  • PPAbner:兄弟,我也用这个,可是当我检测内存消耗的时候,发现SD 很好内存的!不信可以用苹果的instrument 试一试!
    xiAo__Ju:@PP_Abner 我公司是swift,只是之前用过!你看看我的思路可以自己写一个!
  • 五月飞:SD这么多人用,显然是经过了众多开发者的不断验证,这点无容质疑。美中不足的是它没有实现无缝滚动的逻辑,设定的在滚过100次以后返回重新滚动,我拜读过他的代码,自己也动手写了一个swift版的https://github.com/eppeo/FYSliderView/tree/master/FYSliderView有需要的同学请参考,也请批评指正
  • Angzn:SD有个很大的BUG,被你们吹捧成这样
    xiAo__Ju:@Angzn 那你提issue啊,我也没有吹捧啊!相比较它就是还可以啊!
  • TimeLaoKey:谢谢分享
  • a314dc5e14d7:不错不错
  • 一只风流的dog:不错 Mark

本文标题:iOS那些“垃圾”的轮播

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