在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.运行结果
三.使用第三方库——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
这样我们就实现了轮播图的效果:
三.FSPagerView和ZCycleView的区别
标签:轮播,make,iOS,----,func,图片,self,pageControl From: https://blog.csdn.net/qq_74177011/article/details/142178978
- 设计理念:FSPagerView更侧重于屏幕滑动和视图控制器的滑块,而ZCycleView则专注于图片轮播。
- 功能特性:FSPagerView提供了更丰富的页面间过渡动画和自定义选项,而ZCycleView则更侧重于图片轮播的自定义和与其他UI组件的结合使用。
- 应用场景:FSPagerView适用于多种场景,如Banner视图、产品展示、欢迎/引导页面等,而ZCycleView则更适用于需要图片轮播的场景。