swift3.0封装引导页和轮播图
第一次写博客,文章若有不足之处,欢迎点出。
最新在写一个新的项目,用到了引导页,所以用UICollectionView封装了一下,此demo可以切换引导页和轮播图两种模式,设置代理,实现方法即可,简单便捷,参数:图片数组,模式切换,是否循环,循环速度等。不多说直接上代码,以后会继续完善。
一、代理方法
传入需要的参数,例如:
extension AppDelegate: GGGuidePageVCDataSoure{
func getImgArrayAndSenconds() -> ([Any], Int) {
/// 图片数组
let arr = ["chen.jpg","hai1.jpg","mei.jpg","mei2.jpg"]
/// 每x秒执行一次
let senNum = 1
return (arr,senNum)
}
}
extension AppDelegate: GGGuidePageVCDelegate{
/// 是否自动翻页
func getPageBool() -> Bool {
return true
}
/// 是否循环
func getCycleBool() -> Bool {
return true
}
/// page的位置
func getPageFrame() -> PageFrameEnum{
return PageFrameEnum.centerPage
}
}
注:PageFrameEnum
是一个枚举值:
enum PageFrameEnum {
case leftBottom
case centerPage
case rightBottom
}- 简单易懂吧!
二、下面是控制器中具体的实现:
protocol GGGuidePageVCDataSoure: NSObjectProtocol{
/// 返回一个带数组和int的元组
func getImgArrayAndSenconds() -> ([Any],Int)
}
protocol GGGuidePageVCDelegate: NSObjectProtocol {
func getPageBool() -> Bool
func getCycleBool() -> Bool
func getPageFrame() -> PageFrameEnum
}
enum PageFrameEnum {
case leftBottom
case centerPage
case rightBottom
}
class GGGuidePageViewController: UICollectionViewController {
/// 图片名称数组
fileprivate lazy var imgNameArray = [Any]()
/// 翻页秒数
fileprivate lazy var pageSeconds: Int = Int()
/// 是否翻页
fileprivate lazy var pageYesAndNo: Bool = true
/// 是否循环
fileprivate lazy var cycleYesAndNo: Bool = false
var delegate: GGGuidePageVCDelegate?
var dataSoure: GGGuidePageVCDataSoure?
fileprivate var timer:DispatchSourceTimer?
fileprivate lazy var pageControl: UIPageControl = UIPageControl()
fileprivate var layout = UICollectionViewFlowLayout()
override func viewDidLoad() {
super.viewDidLoad()
/// 注册
self.collectionView!.register(GGGuidePageCell.self, forCellWithReuseIdentifier:guideCell)
/// 代理赋值
let tuples = dataSoure?.getImgArrayAndSenconds()
imgNameArray = tuples!.0
pageSeconds = tuples!.1
let pageBool = delegate?.getPageBool()
pageYesAndNo = pageBool!
let cycleBool = delegate?.getCycleBool()
cycleYesAndNo = cycleBool!
/// 设置页控制器
configurePageController()
/// collectionView基本设置
basicSetting()
/// 设置自动滚动计时器
configureAutoScrollTimer()
}
init() {
super.init(collectionViewLayout:layout)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func basicSetting(){
self.collectionView?.isPagingEnabled = true
/// 回弹效果
self.collectionView?.bounces = true
self.collectionView?.showsHorizontalScrollIndicator = false
self.collectionView?.backgroundColor = UIColor.white
/// 水平回弹
self.collectionView?.alwaysBounceHorizontal = true
layout.scrollDirection = UICollectionViewScrollDirection.horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.itemSize = UIScreen.main.bounds.size
}
/// 引导页、轮播图双模式切换
func configureAutoScrollTimer(){
if cycleYesAndNo == true {
/// 循环(轮播图模式)
if pageYesAndNo == true {
// 定义需要计时的时间
var timeCount = 0
// 在global线程里创建一个时间源
timer = DispatchSource.makeTimerSource(queue:DispatchQueue.global())
// 设定这个时间源是每秒循环一次,立即开始
timer?.scheduleRepeating(deadline: .now() , interval: .seconds(pageSeconds))
// 设定时间源的触发事件
timer?.setEventHandler {
// 每秒计时一次
timeCount = timeCount + 1
// 返回主线程处理一些事件,更新UI等等
DispatchQueue.main.async {
let offset = CGPoint(x: CGFloat(timeCount % self.imgNameArray.count) * (self.collectionView?.bounds.width)!, y: 0)
self.collectionView?.setContentOffset(offset, animated: true)
self.pageControl.currentPage = timeCount % self.imgNameArray.count
debugPrint("2222")
}
}
// 启动时间源
timer?.resume()
}else{
debugPrint("不执行引导页翻页")
}
}else{
/// 不循环(引导页模式)
if pageYesAndNo == true {
// 定义需要计时的时间
var timeCount = 0
// 在global线程里创建一个时间源
timer = DispatchSource.makeTimerSource(queue:DispatchQueue.global())
// 设定这个时间源是每秒循环一次,立即开始
timer?.scheduleRepeating(deadline: .now(), interval: .seconds(pageSeconds))
// 设定时间源的触发事件
timer?.setEventHandler(handler: {
// 每秒计时一次
timeCount = timeCount + 1
// 时间到了取消时间源
if timeCount >= self.imgNameArray.count {
self.timer?.cancel()
DispatchQueue.main.async {
debugPrint("1111")
}
}else{
// 返回主线程处理一些事件,更新UI等等
DispatchQueue.main.async {
let offset = CGPoint(x: CGFloat(timeCount) * (self.collectionView?.bounds.width)!, y: 0)
self.collectionView?.setContentOffset(offset, animated: true)
self.pageControl.currentPage = timeCount
debugPrint("2222")
}
}
})
// 启动时间源
timer?.resume()
}else{
debugPrint("不执行引导页翻页")
}
}
}
func configurePageController(){
let pageFrame = delegate?.getPageFrame()
switch pageFrame!{
case .leftBottom:
self.pageControl = UIPageControl(frame: CGRect(x:60,y: kHeight - 20, width: 120, height: 20))
pageSetting()
case .centerPage:
self.pageControl = UIPageControl(frame: CGRect(x: kWidth/2-60,y: kHeight - 20, width: 120, height: 20))
pageSetting()
case .rightBottom:
self.pageControl = UIPageControl(frame: CGRect(x: 300,y: kHeight - 20, width: 120, height: 20))
pageSetting()
}
}
func pageSetting(){
self.pageControl.numberOfPages = imgNameArray.count
self.pageControl.isUserInteractionEnabled = false
// 非当前页颜色
self.pageControl.pageIndicatorTintColor = UIColor.yellow
// 当前页颜色
self.pageControl.currentPageIndicatorTintColor = UIColor.red
self.view.addSubview(self.pageControl)
}
/// btn的点击事件
func inToLoginAction(){
APPDelegateInstance.restore(LoginViewController())
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
/// MARK: UICollectionViewDataSource
extension GGGuidePageViewController{
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imgNameArray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: guideCell, for: indexPath as IndexPath) as! GGGuidePageCell
cell.imgView.image = UIImage(named: imgNameArray[indexPath.row] as! String)
cell.startButton.addTarget(self, action: #selector(inToLoginAction), for: .touchUpInside)
cell.setIndexPath(indexPath: indexPath, count: imgNameArray.count)
return cell
}
}
/// MARK: UICollectionViewDelegate
extension GGGuidePageViewController{
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let imgWidth = scrollView.frame.width
let offsetX = scrollView.contentOffset.x
let pageIndex = offsetX / imgWidth
self.pageControl.currentPage = Int(pageIndex)
}
/// 滑动结束方法或者正在滑动--取消时间源
}
三、结语
功能还不是很完美,但是足够普通功能的支撑,也可以给一些小伙伴们当做参考。用swift时间还不长,有些地方代码的简化还不够,写出优雅的代码是我的目标,以后会继续努力~在这之中遇到的一些坑,其中一个比较重要的就是GCD定时器的使用,先不说GCD在swift语法中的变化,在设置timer的时候记得最好是使用强引用的变量!!!!说三遍!!!!!!