iOS开发----轮播图实现

在iOS开发中,实现图片轮播的方法有很多,在这里介绍三种方法。

轮播图片资源准备——SDWebImage

这里我们通过第三方库SDWebImage来加载网络图片

首先通过CocoaPods下载:

接着,从网站上找想要轮播图片的地址,复制下来,y一般是下图这样,

在代码中,使用UIImageView的扩展方法sd_setImage(with:)来加载图片,并指定图片的URL。,如图:

注意:如果是这样操作的话,点击运行,会报紫色感叹号,这是运行时出错了,错误原因如下:

报错的原因在于我们复制的图片地址是HTTP,这是一个不安全的连接来访问服务,但是iOS 9及以上版本的操作系统默认启用了传输层安全(TLS),并且要求所有的HTTP连接必须通过TLS进行加密。这是为了提高数据传输的安全性。所以我们有两种解决办法:

1.将图片地址url的"http"改为"https"

2.打开Info.plist文件(Info.plist是苹果操作系统(iOS, macOS, watchOS, tvOS) 应用程序中的配置文件,用于存储应用程序的各种信息和配置设置),添加配置信息,如图

注意把Allow Arbitrary Loads 的值由No改为YES,这样前期的图片准备工作就完成了。

一.分页控制器——UIPageViewController

UIPageViewController是个高度可配置的类,你可以进行如下配置:

  • 分页的方向——水平或垂直
  • 翻页的样式——书卷翻页或者滑动翻页
  • 书脊位置——只有书卷翻页样式有效
  • 页面间距——只有滑动翻页样式有效,用来定义页面间距(inter-page spacing)

UIPageViewController类似一个视图容器,其中每个具体的视图由各自的ViewController进行维护管理,UIPageViewController只进行协调与动画布置。因此也叫分页控制器,下图可以很好的展现出UIPageViewControlelr的使用结构:

为了演示,我们通过使用改控件来实现一个图片轮播的小demo

1.定义UIPageViewController和PageControl

   lazy var pageViewController:UIPageViewController = {
        let pageVC = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
        pageVC.delegate = self
        pageVC.dataSource = self
        pageVC.setViewControllers([viewControllers[0]], direction: .forward, animated: true)
        return pageVC
    }()
    lazy var pageControl: UIPageControl = {
        let pc = UIPageControl()
        pc.backgroundColor = .clear
        pc.currentPage = 0
        pc.isEnabled = false
        pc.numberOfPages = viewControllers.count
        pc.pageIndicatorTintColor = .yellow
        pc.currentPageIndicatorTintColor = .black
        return pc
    }()

2.设置分页子视图

import UIKit
import SnapKit

class ImageViewController: UIViewController {
    
    lazy var ImageView:UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white
        self.view.addSubview(ImageView)
        ImageView.snp.makeConstraints { make in
            make.left.equalTo(50)
            make.right.equalTo(-50)
            make.centerY.equalToSuperview()
            make.height.equalTo(300)
        }
    }
    

}
  var viewControllers = [ImageViewController]()
    override func viewDidLoad() {
        super.viewDidLoad()
        for i in 0..<urls.count {
            let view1 = ImageViewController()
            let url = URL(string: urls[i])
            view1.ImageView.sd_setImage(with: url)
            viewControllers.append(view1)
        }
        setUpUI()
    }

3.setUpUI()实现

  func setUpUI() {
//        添加子视图控制器到父视图上
        addChild(pageViewController)
        view.addSubview(pageViewController.view)
        //在转换子视图控制器后 立即实现子视图控制器上的方法
        pageViewController.didMove(toParent: self)
        print(pageControl.numberOfPages)
        self.view.addSubview(pageControl)
        pageControl.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.width.equalTo(width - 140)
            make.centerY.equalToSuperview().offset(150)
            make.height.equalTo(30)
        }
    }

4.代理方法实现


extension ViewController:UIPageViewControllerDelegate,UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        pageControl.currentPage = (pageControl.currentPage == 0) ? urls.count : pageControl.currentPage - 1
        return viewControllers[pageControl.currentPage]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        pageControl.currentPage = (pageControl.currentPage == urls.count - 1) ? 0 : pageControl.currentPage + 1
        return viewControllers[pageControl.currentPage]
    }
    
    
    
}

效果如下:

https://live.csdn.net/v/424264

通过这种方式创建轮播图,有一些明显的弊端,因为UIPageViewController本身是分页控制器,它控制的是子控制器的变换方式,因此创建时需要多创建几个控制器,操作的不是图片而是图片所在的控制器。

二.使用第三方库——FSPagerView

FSPageView是基于UICollectionView来实现的屏幕滑动库,特别适用于制作轮播图、产品展示、欢迎指南页面和视图控制器滑块。

主要特性如下:

  • 无限滚动
  • 自动滑动
  • 水平与垂直分页
  • 完全可自定义项目,附带预设的横幅样式项目
  • 全面可定制的 分页控制
  • 丰富的内置3D转换效果

接下来让我们看看如何实现:

1.导入项目

pod 'FSPagerView'

2.创建轮播视图

    func createFSpagerView() {
        //设置代理
        FSView.delegate = self
        FSView.dataSource = self
        //设置Item的宽高
        FSView.itemSize = CGSize(width: width - 40,height: height/4.4)
        //设置轮播以及滑动方向
        FSView.scrollDirection = .horizontal
        //设置是否无限循环
        FSView.isInfinite = true
        //设置自动滑动间隔时间
        FSView.automaticSlidingInterval = 1.2
        self.view.addSubview(FSView)
        FSView.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(20)
            make.right.equalToSuperview().offset(-20)
            make.centerY.equalToSuperview()
            make.height.equalTo(height/4.3)
        }
        //设置图片滚动方式
        FSView.transformer  = FSPagerViewTransformer(type:  .linear)
        //注册
        FSView.register(FSPagerViewCell.self, forCellWithReuseIdentifier: cellID)
    }

3.创建多页控件(小圆点)FSPageControl

   func createFSControl() {

        FSControl.numberOfPages = urls.count
        FSControl.contentHorizontalAlignment = .center
        FSControl.currentPage = 0
        FSControl.hidesForSinglePage  = true
        FSControl.setStrokeColor(.green, for: .normal)
        FSControl.setStrokeColor(.green, for: .selected)
        FSControl.setFillColor(.green, for: .selected)
        self.view.addSubview(FSControl)
        FSControl.snp.makeConstraints { make in
            make.centerX.equalTo(self.FSView)
            make.width.equalTo(self.FSView.snp.width)
            make.bottom.equalTo(self.FSView.snp.bottom).offset(-5)
            make.height.equalTo(20)
        }
    }

3.代理方法实现

extension ViewController:FSPagerViewDelegate,FSPagerViewDataSource {
    func numberOfItems(in pagerView: FSPagerView) -> Int {
        //item数量
        urls.count
    }
    
    func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
//        创建cell
        let cell = pagerView.dequeueReusableCell(withReuseIdentifier: cellID, at: index)
        let url = URL(string:urls[index])
        cell.imageView!.sd_setImage(with: url)
        return cell
    }
    
    func pagerViewWillEndDragging(_ pagerView: FSPagerView, targetIndex: Int) {
        //当图片Page将要结束拖拽,就是图片从出现到离开后的方法
        print("\(targetIndex)图片离开屏幕")
    }
    
    func pagerView(_ pagerView: FSPagerView, willDisplay cell: FSPagerViewCell, forItemAt index: Int) {
        //当图片或者Item出现滚动后调用方法,通过该方法,可以使pagecontrol实时随图片滚动而更新
        self.FSControl.currentPage = index
    }
    

4.运行结果

轮播图2-CSDN直播

三.使用第三方库——ZCycleView

  • ZCycleView是一个使用UICollectionView实现常见图片无限轮播的开源项目‌。它支持自定义cell、自定义pageControl以及多种轮播样式‌。主要用于图片轮播场景,如新闻、广告等内容的展示‌。具有以下特点:
  • 提供了基本的轮播功能,如无限滚动和自定义轮播样式‌。
  • 可以与其他UI组件库结合使用,如SDWebImage用于图片加载,SnapKit用于自动布局‌。

让我们通过以下这个小demo来体验一下:

1.导入项目

通过CocoaPods下载:

pod 'ZCycleView'

2.创建一个ZcycleView

补充这里的占位图片的意思是当我轮播图的实际图片没有加载时,就用这张图片作为代替。

3.实现代理方法

这里的前两个方法是必须实现的,最后一个方法的作用是更换轮播图的pageControll(就是指示点)的设置信息

extension ViewController: ZCycleViewProtocol {

    
    public func cycleViewRegisterCellClasses() -> [String : AnyClass] {
        return ["ZCycleViewCellID":FSPageViewCell.self]
    }
    
    public func cycleViewConfigureCell(collectionView: UICollectionView, cellForItemAt indexPath: IndexPath, realIndex: Int) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ZCycleViewCellID", for: indexPath) as! FSPageViewCell
        
        let url = URL(string:urls[realIndex])
        
        cell.imageView.sd_setImage(with: url)
        
//        cell.imageView.image = images[realIndex]
        return cell
    }
    
    func cycleViewConfigurePageControl(_ cycleView: ZCycleView, pageControl: ZPageControl) {
        pageControl.isHidden = false
        pageControl.currentPageIndicatorTintColor = .green
        pageControl.pageIndicatorTintColor = .yellow
        pageControl.dotSize = .init(width: 10, height: 10)
        pageControl.frame = CGRect(x: 0, y: cycleView.bounds.height-25, width: cycleView.bounds.width, height: 25)
    }
}

这里注意第二个实现方法我们使用的数组索引是realIndex,不是indexPath.row,不然会数组越界。这是为什么呢?

如果我们可以查看一下第三方库相关源码:

从源码中可以发现,我们的代理方法中的第三个参数RealIndex实际做了处理,会等于indexPath.item对我们实际Item取模后的值,那么indexpath.item是多少呢?因为我们的section只有1个,所以我们这个值相当于是indexPath.row,与上面第一个方法返回的itemsCount有关,那我们看看itemsCount的值是然后赋值的吧!

这里可以发现,itemsCount做了通过三目运算符的方式做了条件赋值,前置逻辑条件realItemsCount<=1 和 !isInfinite)是false,因此其值会等于realItemsCount *200,所以使用indexPath.row会发生数组越界。

3.自定义Cell

在代理方法的第二个实现方法里我们所使用的cell是自定义的,这里的cell是UICOllectionViewCell

这样我们就实现了轮播图的效果:

轮播图3-CSDN直播

三.FSPagerView和ZCycleView的区别

  • 设计理念‌:FSPagerView更侧重于屏幕滑动和视图控制器的滑块,而ZCycleView则专注于图片轮播。
  • 功能特性‌:FSPagerView提供了更丰富的页面间过渡动画和自定义选项,而ZCycleView则更侧重于图片轮播的自定义和与其他UI组件的结合使用。
  • 应用场景‌:FSPagerView适用于多种场景,如Banner视图、产品展示、欢迎/引导页面等,而ZCycleView则更适用于需要图片轮播的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值