iOS|iOS JXBanner - (多功能无限轮播图框架)

(JXBanner 支持多种动画变换, 支持纯代码布局和Xib布局) JXBanner依赖于JXPageControl,并包含许多自定义接口,如转换动画、视图结构和设置

    1. 开发环境: Xcode 7
    1. 运行条件: iOS(8.0+)
  • 开源框架:github地址

【iOS|iOS JXBanner - (多功能无限轮播图框架)】(如果使用有什么问题,可以留言,欢迎一起学习,欢迎star)
Installation [安装]
安装,只需将以下面代码添加到您的Podfile:
platform :ios, '8.0'target 'TargetName' do pod 'JXBanner' end

UI效果
  • default
不需要设置JXBanner -> JXBannerLayoutParams
iOS|iOS JXBanner - (多功能无限轮播图框架)
文章图片
default.gif
  • JXBannerTransformLinear
iOS|iOS JXBanner - (多功能无限轮播图框架)
文章图片
linear.gif
  • JXBannerTransformCoverflow
iOS|iOS JXBanner - (多功能无限轮播图框架)
文章图片
coverflow.gif
  • custom
需要实现JXBannerTransformable协议, 修改 UICollectionViewLayoutAttributes -> transform3D 或 transform 属性
iOS|iOS JXBanner - (多功能无限轮播图框架)
文章图片
custom.gif Frame set [框架集合]

Banner 轮播图框架公用类文件
  • API ---> 开发者可以调用的所有接口
  • Cell ---> 框架提供cell基类 (如果想自定义cell内容, 可以新建cell继承于JXBannerBaseCell)
  • Common ---> 框架公用类文件
  • Transform ---> 动画效果类文件 ( 如果框架提供的动画效果不能满足开发者需求, 可以新建实现JXBannerTransformable协议的struct/class, 修改 UICollectionViewLayoutAttributes -> transform3D 或 transform 属性)
PageControl 指示器类文件
  • JXBannerPageControlBuilder ---> pageControl的构建者类
  • JXBannerPageControlDefault ---> 框架默认的pageControl样式 (可以通过实现JXBannerDataSource -> 【jxBanner(pageControl banner: numberOfPages: coverView: builder:) -> JXBannerPageControlBuilder】协议方法修改样式)
JXBanner 重要文件介绍

JXBannerParams 【banner 属性】
  • isAutoPlay ---> 自动播放
  • isBounces ---> 边界能否越界滑动
  • timeInterval ---> 播放调度间隔
  • isShowPageControl ---> 是否加载内部指示器(JXPageControl(框架特色))
  • cycleWay ---> 轮播方式(框架特色) (forward:无线向右播放, skipEnd:首尾自定义动画跳转, rollingBack:左右回滚模式)
  • edgeTransitionType ---> cycleWay 使用 skipEnd 中 可以选取动画方式
  • edgeTransitionSubtype ---> cycleWay 使用 skipEnd 中 可以选取动画方式
JXBannerLayoutParams 【banner布局、动画属性】
  • itemSize ---> cell大小。
  • itemSpacing --->cell左右边距。
  • layoutType ---> 动画效果JXBannerTransformable(框架特色)
  • minimumScale ---> cell 缩放系数。
  • minimumAlpha ---> cell 透明度系数。
  • maximumAngle ---> cell 旋转系数。
  • rateOfChange ---> cell 变化系数。
  • rateHorisonMargin ---> cell 水平间距调整系数。
JXBannerCellRegister 【cell注册构建者】
  • type ---> 注册cell的类型,必须是JXBannerBaseCell的子类
  • reuseIdentifier ---> cell重用标识
    var type: JXBannerBaseCell.Type
    var reuseIdentifier: String
JXBanner 使用

Example 1
  • 默认实现示例

import SnapKit import JXBannerclass JXDefaultVC: UIViewController {var pageCount = 5lazy var banner: JXBanner = { let banner = JXBanner() banner.backgroundColor = UIColor.black banner.placeholderImgView.image = UIImage(named: "banner_placeholder") banner.delegate = self banner.dataSource = self return banner }()override func viewDidLoad() { super.viewDidLoad() view.addSubview(banner) banner.snp.makeConstraints { (maker) in maker.left.right.equalTo(view) maker.height.equalTo(250) maker.top.equalTo(view.snp_top).offset(100) } self.automaticallyAdjustsScrollViewInsets = false }deinit { print("\(#function) ----------> \(#file.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? #file)") } }//MARK:- JXBannerDataSource extension JXDefaultVC: JXBannerDataSource {// 注册重用Cell标识 func jxBanner(_ banner: JXBannerType) -> (JXBannerCellRegister) { return JXBannerCellRegister(type: JXBannerCell.self, reuseIdentifier: "JXDefaultVCCell") }// 轮播总数 func jxBanner(numberOfItems banner: JXBannerType) -> Int { return pageCount }// 轮播cell内容设置 func jxBanner(_ banner: JXBannerType, cellForItemAt index: Int, cell: JXBannerBaseCell) -> JXBannerBaseCell { let tempCell: JXBannerCell = cell as! JXBannerCell tempCell.layer.cornerRadius = 8 tempCell.layer.masksToBounds = true tempCell.imageView.image = UIImage(named: "banner_placeholder") tempCell.msgLabel.text = String(index) + "---来喽来喽,他真的来喽~" return tempCell }// banner基本设置(可选) func jxBanner(_ banner: JXBannerType, layoutParams: JXBannerLayoutParams) -> JXBannerLayoutParams { return layoutParams .itemSize(CGSize(width: UIScreen.main.bounds.width - 40, height: 200)) .itemSpacing(20) } }//MARK:- JXBannerDelegate extension JXDefaultVC: JXBannerDelegate {// 点击cell回调 public func jxBanner(_ banner: JXBannerType, didSelectItemAt index: Int) { print(index) }}

Example 2
  • 个性化设置
import SnapKit import JXBanner import JXPageControlclass JXCustomVC: UIViewController {var pageCount = 5lazy var linearBanner: JXBanner = {[weak self] in let banner = JXBanner() banner.placeholderImgView.image = UIImage(named: "banner_placeholder") banner.backgroundColor = UIColor.black banner.indentify = "linearBanner" banner.delegate = self banner.dataSource = self return banner }()lazy var converflowBanner: JXBanner = { let banner = JXBanner() banner.placeholderImgView.image = UIImage(named: "banner_placeholder") banner.backgroundColor = UIColor.black banner.indentify = "converflowBanner" banner.delegate = self banner.dataSource = self return banner }()override func viewDidLoad() { super.viewDidLoad() view.addSubview(linearBanner) view.addSubview(converflowBanner) linearBanner.snp.makeConstraints {(maker) in maker.left.right.equalTo(view) maker.height.equalTo(200) maker.top.equalTo(view.snp_top).offset(100) }converflowBanner.snp.makeConstraints {(maker) in maker.left.right.height.equalTo(linearBanner) maker.top.equalTo(linearBanner.snp_bottom).offset(100) }self.automaticallyAdjustsScrollViewInsets = false }deinit { print("\(#function) ----------> \(#file.components(separatedBy: "/").last?.components(separatedBy: ".").first ?? #file)") } }//MARK:- JXBannerDataSource extension JXCustomVC: JXBannerDataSource {// 注册重用Cell标识 func jxBanner(_ banner: JXBannerType) -> (JXBannerCellRegister) {if banner.indentify == "linearBanner" { return JXBannerCellRegister(type: JXBannerCell.self, reuseIdentifier: "LinearBannerCell") }else { return JXBannerCellRegister(type: JXBannerCell.self, reuseIdentifier: "ConverflowBannerCell") } }// 轮播总数 func jxBanner(numberOfItems banner: JXBannerType) -> Int { return pageCount }// 轮播cell内容设置 func jxBanner(_ banner: JXBannerType, cellForItemAt index: Int, cell: JXBannerBaseCell) -> JXBannerBaseCell { let tempCell: JXBannerCell = cell as! JXBannerCell tempCell.layer.cornerRadius = 8 tempCell.layer.masksToBounds = true tempCell.imageView.image = UIImage(named: "banner_placeholder") tempCell.msgLabel.text = String(index) + "---来喽来喽,他真的来喽~" return tempCell }// banner基本设置(可选) func jxBanner(_ banner: JXBannerType, params: JXBannerParams) -> JXBannerParams {if banner.indentify == "linearBanner" { return params .timeInterval(2) .cycleWay(.forward) }else { return params .timeInterval(3) .cycleWay(.forward) } }// banner布局、动画设置 func jxBanner(_ banner: JXBannerType, layoutParams: JXBannerLayoutParams) -> JXBannerLayoutParams {if banner.indentify == "linearBanner" { return layoutParams .layoutType(JXBannerTransformLinear()) .itemSize(CGSize(width: 250, height: 190)) .itemSpacing(10) .rateOfChange(0.8) .minimumScale(0.7) .rateHorisonMargin(0.5) .minimumAlpha(0.8) }else { return layoutParams .layoutType(JXBannerTransformCoverflow()) .itemSize(CGSize(width: 300, height: 190)) .itemSpacing(0) .maximumAngle(0.25) .rateHorisonMargin(0.3) .minimumAlpha(0.8) } }// 自定义pageControl样式、布局 //(基于jxPageControl, 如果不适用JXPageControl, 设置isShowPageControl = false, 内部pageControl将不会再次加载 ) func jxBanner(pageControl banner: JXBannerType, numberOfPages: Int, coverView: UIView, builder: JXBannerPageControlBuilder) -> JXBannerPageControlBuilder {if banner.indentify == "linearBanner" { let pageControl = JXPageControlScale() pageControl.contentMode = .bottom pageControl.activeSize = CGSize(width: 15, height: 6) pageControl.inactiveSize = CGSize(width: 6, height: 6) pageControl.activeColor = UIColor.red pageControl.inactiveColor = UIColor.lightGray pageControl.columnSpacing = 0 pageControl.isAnimation = true builder.pageControl = pageControl builder.layout = { pageControl.snp.makeConstraints { (maker) in maker.left.right.equalTo(coverView) maker.top.equalTo(coverView.snp_bottom).offset(10) maker.height.equalTo(20) } } return builder}else { let pageControl = JXPageControlExchange() pageControl.contentMode = .bottom pageControl.activeSize = CGSize(width: 15, height: 6) pageControl.inactiveSize = CGSize(width: 6, height: 6) pageControl.activeColor = UIColor.red pageControl.inactiveColor = UIColor.lightGray pageControl.columnSpacing = 0 builder.pageControl = pageControl builder.layout = { pageControl.snp.makeConstraints { (maker) in maker.left.right.equalTo(coverView) maker.top.equalTo(coverView.snp_bottom).offset(10) maker.height.equalTo(20) } } return builder }}}//MARK:- JXBannerDelegate extension JXCustomVC: JXBannerDelegate {// 点击cell回调 public func jxBanner(_ banner: JXBannerType, didSelectItemAt index: Int) { print(index) }// 设置自定义覆盖View, 比如添加自定义外部pageControl和布局 func jxBanner(_ banner: JXBannerType, coverView: UIView) { let title = UILabel() title.frame = CGRect(x: 0, y: 0, width: 100, height: 30) title.text = "JXBanner" title.textColor = UIColor.red title.font = UIFont.systemFont(ofSize: 16) coverView.addSubview(title) }// 最中心显示cell 索引 func jxBanner(_ banner: JXBannerType, center index: Int) { print(index) } }

Example 3 如果框架提供的动画效果不能满足开发者需求:
    1. 轮播图动画样式开发者可以自定义实现, 只要是新建实现JXBannerTransformable协议的struct/class, 修改 UICollectionViewLayoutAttributes -> transform3D 或 transform 属性)
// //JXCustomTransform.swift //JXBanner_Example // //Created by 谭家祥 on 2019/7/30. //Copyright ? 2019 CocoaPods. All rights reserved. //import UIKit import JXBannerstruct JXCustomTransform: JXBannerTransformable {public func transformToAttributes(collectionView: UICollectionView, params: JXBannerLayoutParams, attributes: UICollectionViewLayoutAttributes) {let collectionViewWidth = collectionView.frame.width if collectionViewWidth <= 0 { return }let centetX = collectionView.contentOffset.x + collectionViewWidth * 0.5; let delta = abs(attributes.center.x - centetX) let calculateRate = 1 - delta / collectionViewWidth let angle = min(delta / collectionViewWidth * (1 - params.rateOfChange), params.maximumAngle) let alpha = max(calculateRate, params.minimumAlpha)applyCoverflowTransformToAttributes(viewCentetX: centetX, attributes: attributes, params: params, angle: angle, alpha: alpha, calculateRate: calculateRate) }func applyCoverflowTransformToAttributes(viewCentetX: CGFloat, attributes: UICollectionViewLayoutAttributes, params: JXBannerLayoutParams, angle: CGFloat, alpha: CGFloat, calculateRate: CGFloat) -> Void { var transform3D: CATransform3D = CATransform3DIdentitylet location = JXBannerTransfrom.itemLocation(viewCentetX: viewCentetX, itemCenterX: attributes.center.x)var _angle = angle var _alpha = alpha var _translateX: CGFloat = 0 var _translateY: CGFloat = 0 attributes.zIndex = 0switch location { case .left: _angle = angle _translateX = 0.2 * attributes.size.width * (1 - calculateRate) / 4 _translateY = 0.4 * attributes.size.height * (1 - calculateRate)case .right: _angle = -angle _translateX = -0.2 * attributes.size.width * (1 - calculateRate) / 4 _translateY = 0.4 * attributes.size.height * (1 - calculateRate)case .center: _angle = 0 _alpha = 1 _translateY = 0 attributes.zIndex = 10000 }transform3D = CATransform3DTranslate(transform3D, _translateX, _translateY, 0) transform3D = CATransform3DRotate(transform3D, -CGFloat.pi * _angle, 0, 0, 1) attributes.alpha = _alpha attributes.transform3D = transform3D }}

    1. 设置自定义实现动画
JXBannerDataSource -> 【jxBanner(_ banner: layoutParams: ) -> JXBannerLayoutParams】
// JXCustomTransform()func jxBanner(_ banner: JXBannerType, layoutParams: JXBannerLayoutParams) -> JXBannerLayoutParams {return layoutParams .layoutType(JXCustomTransform()) }

更多设置可以参考示例 Demo地址

    推荐阅读