教你写个图片轮播

作者: Sheepy | 来源:发表于2015-12-31 15:33 被阅读1126次
图片轮播.gif

这是一个图片轮播的 Demo,上半部分用 CollectionView 实现,没有无限循环效果,下半部分是用 ScrollView 实现的,自动无限轮播。代码地址在这里

上次用 CollectionView 实现了一个多表视图,这次本来想用同样的思路实现个图片轮播,结果发现并不是很方便。主要是“无限循环滑动”的效果单纯用 CollectionView 的接口的话基本做不到,要做也只能是把待显示图片的数量 * N(N是一个很大的数),可以做到在比较长的时间内一直向后轮播,因为 Cell 的复用机制,真正使用的只有两个 Cell 对象,所以不用担心内存爆炸。但是这样做不到手势滑动的“首尾连接”,就是无论往左还是往右都可以无限滑动,要达到这样的效果,还是得用到 ScrollView 的接口,所以我觉得还不如直接用 ScrollView 写好了。

用 ScrollView 实现“首尾连接”有一种常见的思路:

frame_content.png

白色边框代表 ScrollView 的 frame,蓝色部分是 content。简单来说就是在要显示的图片的左右两边各加一张图片作为桥接。譬如当前显示的是第一张图片(img1),按理说再用手往右滑动的话啥都没有了,但现在我在img1的左边又加了一张img3,这样在向右滑动的时候我们还能看到 img3,然后在滑动即将停下的时候,快速切换到第四个位置的 img3,所以最左边的 img3 永远不会在静止的时候显示。现在如果再向右滑动的话,就正常滑到 img2。向左滑动的时候同理,在滑到最后的那张 img1的一瞬间,切换到第二个位置的 img1。代码如下:

extension AutoScrollView: UIScrollViewDelegate {
    //速度变慢,即将停下的时候调用
    func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        //因为可以左右滑,所以不能简单地加1,而要通过contentofff计算要滑到第几张图片
        let page = Int(scrollView.contentOffset.x / width)
        if page == 0 {
            scrollView.contentOffset.x = width * CGFloat(imageCount)
        } else if page == imageCount + 1 {
            scrollView.contentOffset.x = width
        }
        
        pageCtrl.currentPage = Int(scrollView.contentOffset.x / width) - 1  
    }
}

上面说的主要是对手势滑动部分的处理,至于按固定时间间隔向右轮播更简单。只要判断一下当前显示的是否是最后一张图片(img3),如果是,那下一张就显示第一张(img1),否则正常显示下一张图片:

func slideByTime() {
    var page = pageCtrl.currentPage + 1
    
    if page == imageCount {
        scrollView.contentOffset.x = width
        page = 0
    } else {
        self.scrollView.contentOffset.x = self.width * CGFloat(page + 1)
    }
    
    pageCtrl.currentPage = page
}

然后用一个计时器定时调用上面这个方法就好了。有的同学可能会直接调用NSTimerscheduledTimerWithTimeInterval方法,但是这个方法有个潜在的危险,一旦将target参数设为selfrepeat参数设为trueNSTimer就会获取当前对象的一个引用,而且极难打破这个引用,这样当前对象就不能被正确释放,极易造成内存泄漏。

解决方法是把要执行的方法作为一个 block 传给 NSTimeruserInfo属性,把target参数设为NSTimer自己,给NSTimer增加一个扩展方法sy_procInvoke,在方法体中执行userInfo

typealias Proc = @convention(block) () -> ()
extension NSTimer {
    class func sy_scheduledTimeerWithTimeInterval(interval: NSTimeInterval, repeats: Bool, repeatHandler: Proc) {
        scheduledTimerWithTimeInterval(interval, target: self, selector: "sy_procInvoke:", userInfo: unsafeBitCast(repeatHandler, AnyObject.self), repeats: true)
    }
    
    class func sy_procInvoke(timer: NSTimer) {
        let proc = unsafeBitCast(timer.userInfo, Proc.self)
        proc()
    }
}

因为userInfo的类型是个 AnyObject,而 Swift 中的闭包是不能转化为AnyObject的,所以得定义一个block类型,就是这一句typealias Proc = @convention(block) () -> (),然后在传给userInfo的时候转化为AnyObject类型。

调用的时候用weak修饰self

//计时器
NSTimer.sy_scheduledTimeerWithTimeInterval(1, repeats: true) { [weak self] in
    self?.slideByTime()
}

这样每隔1秒就会执行slideByTime方法,而且NSTimer没有持有当前对象的引用,任务完成。

相关文章

  • 教你写个图片轮播

    这是一个图片轮播的 Demo,上半部分用 CollectionView 实现,没有无限循环效果,下半部分是用 Sc...

  • 个人博客—轮播器

    个人博客—轮播器 轮播器自动轮播,每张图片淡入淡出 控制按钮和图片描述跟随图片轮播 鼠标悬停图片上方则停止轮播,滑...

  • 沉浸式渐变图片轮播器

    沉浸式渐变图片轮播器 沉浸式渐变图片轮播器

  • JQ实现左右轮播效果

    这篇文章主要是实现图片左右轮播效果,功能:进入页面自动播放图片,鼠标悬浮,暂停图片轮播,鼠标离开,继续图片轮播,点...

  • 常用三方 SDCycleScrollView轮播图

    iOS图片、文字轮播器Git/SDCycleScrollView 滚动轮播图片、文字、可使用本地图片或加载网络图片...

  • 用动画做图片轮播

    图片轮播的新方法,用动画实现轮播: 1.将需要轮播的图片用标签放在同一位置; 2.通过改变各个图片的透明度实现轮播...

  • 第三方库之 banner

    Android 广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式、动画、轮播和切换时间、位置、图片加...

  • 27.jquery 实战-轮播

    代码 1.实现如下轮播效果 要求:渐变轮播,图片淡入淡出轮播会自动循环像左向右点击会展示前/后图片底部显示轮播当前...

  • 无限图片轮播器 --- Objective-C

    KNBannerView 无限循环轮播器:本地图片,网络图片(图片缓存) 一.功能描述及要点 1.无限图片轮播器,...

  • 轮播

    轮播的原理 滑动轮播1.轮播的图片水平排列2.给出一个与图片相同大小的视窗包裹图片列,设置overflow: hi...

网友评论

  • Super_龙: :sweat: 你用scrollView会写用collection view就觉得实现起来不容易....collectionview是继承scrollview的, 一样的逻辑都是可以实现的不信你试一试咯!
    Sheepy:@Super_龙 我是觉得用了 CollectionView 还得用到 ScrollView 的 delegate 才能实现需求的话还不如干脆用 ScrollView 了。我用 CollectionView 也实现过的。
  • 00fe1d42e006:今天不是应该写年终总结嘛~
    Sheepy:@迷糊小小姐 昨天我已经把周总结月总结都给写了😁
    00fe1d42e006:@Sheepy 我正在写这周的工作总结:stuck_out_tongue_winking_eye:
    Sheepy:@迷糊小小姐 好像是这样……那不然待会儿写一个?

本文标题:教你写个图片轮播

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