当前位置: 首页 > news >正文

Swift Control ImageCarouselView图片轮播器(源码)

一直觉得自己写的不是技术而是情怀一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的希望我的这条路能让你们少走弯路希望我能帮你们抹去知识的蒙尘希望我能帮你们理清知识的脉络希望未来技术之巅上有你们也有我。Swift-Banner(图片轮播)示例代码banner本地图片文章目录效果说明使用源码效果说明图片提供一下功能是否开启卡片缩放效果是否自动轮播轮播时间显示 pageControlpageControl颜色设置圆角设置占位图加载网络图片点击事件监听滚动事件使用import UIKit import SnapKit class ViewController:UIViewController{lazy private var imageCarouselView:ImageCarouselView{let viewImageCarouselView()// 是否开启卡片缩放效果view.isCardZoomEnabledtrue// 自动轮播view.isAutoScrolltrue// 轮播时间view.autoScrollTime2// 显示 pageControlview.showPageControltrue// pageControl颜色view.currentPageColor.white view.pageColorUIColor.white.withAlphaComponent(0.3)// 圆角view.layer.cornerRadius16view.clipsToBoundstrue// 占位图view.placeholderImageUIImage(named:placeholder_1)// 网络图片view.remoteImages[https://picsum.photos/id/1015/800/400,https://picsum.photos/id/1016/800/400,https://picsum.photos/id/1018/800/400,https://picsum.photos/id/1020/800/400]// 点击事件view.didTapImageBlock{index inprint(点击了第 \(index) 张图片)}// 滚动事件view.didScrollToIndexBlock{index inprint(当前轮播到第 \(index) 张)}returnview}()override funcviewDidLoad(){super.viewDidLoad()view.backgroundColor.white view.addSubview(imageCarouselView)imageCarouselView.snp.makeConstraints{make in make.top.equalToSuperview().offset(120)make.left.equalToSuperview().offset(20)make.right.equalToSuperview().offset(-20)make.height.equalTo(220)}}}源码import UIKit import SnapKit import Kingfisher class ImageCarouselView:UIView{// MARK: - 对外属性/// 是否自动轮播var isAutoScroll:Booltrue{didSet{setupTimer()}}/// 自动轮播时间var autoScrollTime:TimeInterval3{didSet{setupTimer()}}/// 是否显示 pageControlvar showPageControl:Booltrue{didSet{pageControl.isHidden!showPageControl}}/// pageControl 当前颜色var currentPageColor:UIColor.white{didSet{pageControl.currentPageIndicatorTintColorcurrentPageColor}}/// pageControl 默认颜色var pageColor:UIColorUIColor.white.withAlphaComponent(0.4){didSet{pageControl.pageIndicatorTintColorpageColor}}/// 占位图var placeholderImage:UIImage?/// 本地图片数组var localImages:[String][]{didSet{imageType.localreloadData()}}/// 网络图片数组var remoteImages:[String][]{didSet{imageType.remotereloadData()}}/// 点击图片回调var didTapImageBlock:((Int)-Void)?/// 滚动到图片回调var didScrollToIndexBlock:((Int)-Void)?// MARK: - PrivateprivateenumImageType{caselocalcaseremote}private var imageType:ImageType.local private var timer:Timer?private let maxSections100private var imageCount:Int{switchimageType{case.local:returnlocalImages.countcase.remote:returnremoteImages.count}}// MARK: - UIlazy private var collectionView:UICollectionView{let layoutUICollectionViewFlowLayout()layout.scrollDirection.horizontal layout.minimumLineSpacing0let viewUICollectionView(frame:.zero,collectionViewLayout:layout)view.backgroundColor.clear view.showsHorizontalScrollIndicatorfalse view.isPagingEnabledtrue view.delegateself view.dataSourceself view.register(ImageCarouselCell.self,forCellWithReuseIdentifier:ImageCarouselCell.identifier)returnview}()lazy private var pageControl:UIPageControl{let viewUIPageControl()view.currentPageIndicatorTintColorcurrentPageColor view.pageIndicatorTintColorpageColorreturnview}()// MARK: - Initoverrideinit(frame:CGRect){super.init(frame:frame)buildUI()}required init?(coder:NSCoder){fatalError()}deinit{timer?.invalidate()}}// MARK: - UIextension ImageCarouselView{private funcbuildUI(){addSubview(collectionView)addSubview(pageControl)collectionView.snp.makeConstraints{make in make.edges.equalToSuperview()}pageControl.snp.makeConstraints{make in make.centerX.equalToSuperview()make.bottom.equalToSuperview().offset(-10)}}}// MARK: - Dataextension ImageCarouselView{private funcreloadData(){pageControl.numberOfPagesimageCount collectionView.reloadData()layoutIfNeeded()guard imageCount0else{return}let middleSectionmaxSections/2let startIndexPathIndexPath(item:0,section:middleSection)collectionView.scrollToItem(at:startIndexPath,at:.left,animated:false)setupTimer()}}// MARK: - Timerextension ImageCarouselView{private funcsetupTimer(){timer?.invalidate()timernil guard isAutoScrollelse{return}guard imageCount1else{return}timerTimer.scheduledTimer(timeInterval:autoScrollTime,target:self,selector:#selector(autoScrollAction),userInfo:nil,repeats:true)RunLoop.main.add(timer!,forMode:.common)}objc private funcautoScrollAction(){guard let currentIndexPathcollectionView.indexPathsForVisibleItems.firstelse{return}var nextItemcurrentIndexPath.item1var nextSectioncurrentIndexPath.sectionifnextItemimageCount{nextItem0nextSection1}let nextIndexPathIndexPath(item:nextItem,section:nextSection)collectionView.scrollToItem(at:nextIndexPath,at:.left,animated:true)}}// MARK: - UICollectionViewextension ImageCarouselView:UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{funcnumberOfSections(in collectionView:UICollectionView)-Int{returnmaxSections}funccollectionView(_ collectionView:UICollectionView,numberOfItemsInSection section:Int)-Int{returnimageCount}funccollectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath)-UICollectionViewCell{let cellcollectionView.dequeueReusableCell(withReuseIdentifier:ImageCarouselCell.identifier,for:indexPath)as!ImageCarouselCellswitchimageType{case.local:let imageNamelocalImages[indexPath.item]cell.imageView.imageUIImage(named:imageName)case.remote:let urlStringremoteImages[indexPath.item]guard let urlURL(string:urlString)else{returncell}cell.imageView.kf.setImage(with:url,placeholder:placeholderImage)}returncell}funccollectionView(_ collectionView:UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAt indexPath:IndexPath)-CGSize{returncollectionView.bounds.size}funcscrollViewDidScroll(_ scrollView:UIScrollView){guard imageCount0else{return}let pageInt((scrollView.contentOffset.xscrollView.bounds.width*0.5)/scrollView.bounds.width)%imageCount pageControl.currentPagepage didScrollToIndexBlock?(page)}funccollectionView(_ collectionView:UICollectionView,didSelectItemAt indexPath:IndexPath){didTapImageBlock?(indexPath.item)}funcscrollViewWillBeginDragging(_ scrollView:UIScrollView){timer?.invalidate()}funcscrollViewDidEndDragging(_ scrollView:UIScrollView,willDecelerate decelerate:Bool){setupTimer()}}class ImageCarouselCell:UICollectionViewCell{staticlet identifierImageCarouselCelllazy var imageView:UIImageView{let viewUIImageView()view.contentMode.scaleAspectFill view.clipsToBoundstruereturnview}()overrideinit(frame:CGRect){super.init(frame:frame)contentView.addSubview(imageView)imageView.snp.makeConstraints{make in make.edges.equalToSuperview()}}required init?(coder:NSCoder){fatalError()}}
http://www.zskr.cn/news/1338592.html

相关文章:

  • 六年 CAGR4.9%!流体控制核心元件 比例控制阀市场扩容
  • 3分钟快速上手vJoy:如何为Windows创建专业级虚拟游戏手柄
  • 3分钟搞定M3U8视频下载:N_m3u8DL-CLI-SimpleG完整指南
  • 萝博派对获数千万美元天使+轮融资,开源双足人形机器人发展提速!
  • 台州华声汽车音响改装店推荐,资深玩家都去这几家
  • 四足机器人混合控制框架:强化学习与模型预测的协同创新
  • 独立开发者如何利用Taotoken的多模型与透明计费构建小而美的AI应用
  • AI专著撰写神器揭秘!一键生成20万字专著,轻松搞定写作难题!
  • 3D打印到CAD设计:如何用stltostp轻松实现STL转STEP格式转换
  • 基于高通跃龙IQ-9100端侧多模态大模型赋能具身智能交互系统(1): 从场景理解到VLM部署
  • 如何用DeepEval构建企业级AI模型评估体系:从基础到实战
  • PL2303老芯片Windows 10/11终极救星:3分钟搞定驱动安装
  • 武汉汽车改装哪家靠谱?2026华中汽车影音改装标杆门店推荐-鑫互联车改影音 - GrowthUME
  • Wink下载安装全流程教程(附安装包,2026最新)
  • SSHFS-Win终极指南:如何在Windows上安全访问远程Linux文件系统
  • 终极游戏手柄映射指南:用AntiMicroX让任何PC游戏都支持手柄操作
  • 原型设计工具介绍
  • 计算机专业生打 CTF 全指南:从新手小白到赛事拿分,附实战避坑手册_ctf比赛自己带电脑吗
  • 如何利用Taotoken的用量看板分析与优化团队AI调用成本
  • 终极指南:如何免费解锁Cursor Pro完整功能 - 5分钟永久激活教程
  • PyCharm 代码提示延迟严重怎么优化索引缓存策略?
  • Windows 10/11(64位)上安装 WinQSB——无需虚拟机
  • 在Node.js后端服务中集成Taotoken多模型聚合API的完整指南
  • 2026年AI搜索排名优化公司解析—AI时代企业增长新路径
  • U9的UI插件开发Card功能区上客开的按钮不能正常显示
  • 5个必学技巧:用茉莉花插件让Zotero中文文献管理效率提升300%
  • 情感演绎有多强?顶伯实测愤怒、喜悦、悲伤等 9 种语气
  • 移动安全逆向分析工作流:静态-动态-交互三层实战指南
  • Cursor VIP共享方案终极指南:三步免费解锁AI编程神器的完整教程
  • 如何用Win11Debloat免费为Windows系统瘦身:终极优化指南