引用循环轮播图
核心代码
ImageBrowserCell
import Kingfisher
public struct ImageBrowserModel {
var url: String?
var placeholder: UIImage?
public init(url: String?, placeholder: UIImage?) {
self.url = url
self.placeholder = placeholder
}
}
class ImageBrowserCell: UICollectionViewCell {
private lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 3
scrollView.delegate = self
return scrollView
}()
private lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.layer.masksToBounds = true
imageView.isUserInteractionEnabled = true
return imageView
}()
public private(set) lazy var doubleTap: UITapGestureRecognizer = {
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(tapDoubleDid))
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
return doubleTap
}()
override init(frame: CGRect) {
super.init(frame: frame)
scrollView.frame = bounds
addSubview(scrollView)
imageView.frame = bounds
scrollView.addSubview(imageView)
imageView.addGestureRecognizer(doubleTap)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
resetSize()
}
@objc func tapDoubleDid() {
UIView.animate(withDuration: 0.3, animations: {
if self.scrollView.zoomScale == self.scrollView.minimumZoomScale {
self.scrollView.zoomScale = self.scrollView.maximumZoomScale
} else {
self.scrollView.zoomScale = self.scrollView.minimumZoomScale
}
})
}
func show(model: ImageBrowserModel) {
if let url = model.url {
imageView.kf.setImage(with: URL(string: url), placeholder: model.placeholder)
imageView.kf.setImage(with: URL(string: url), placeholder: model.placeholder) { [weak self] _, _, _, _ in
self?.resetSize()
}
} else {
imageView.image = model.placeholder
resetSize()
}
}
private func resetSize() {
scrollView.frame = contentView.bounds
scrollView.zoomScale = 1.0
if let image = imageView.image {
imageView.frame.size = scaleSize(size: image.size)
imageView.center = scrollView.center
}
}
private func scaleSize(size: CGSize) -> CGSize {
let width = size.width
let height = size.height
let widthRatio = width/UIScreen.main.bounds.width
let heightRatio = height/UIScreen.main.bounds.height
let ratio = max(heightRatio, widthRatio)
return CGSize(width: width/ratio, height: height/ratio)
}
}
// MARK: - UIScrollViewDelegate
extension ImageBrowserCell: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
var centerX = scrollView.center.x
var centerY = scrollView.center.y
centerX = (scrollView.contentSize.width > scrollView.frame.size.width) ? scrollView.contentSize.width/2 : centerX
centerY = (scrollView.contentSize.height > scrollView.frame.size.height) ? scrollView.contentSize.height/2 : centerY
imageView.center = CGPoint(x: centerX, y: centerY)
}
}
ImageBrowserController
open class ImageBrowserController: UIViewController {
private lazy var mainCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 0
layout.scrollDirection = .horizontal
layout.itemSize = UIScreen.main.bounds.size
let collectionView = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: layout)
collectionView.backgroundColor = #colorLiteral(red: 0.1215686275, green: 0.1294117647, blue: 0.1411764706, alpha: 1)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.isPagingEnabled = true
collectionView.register(ImageBrowserCell.self, forCellWithReuseIdentifier: "ImageBrowserCell")
return collectionView
}()
private lazy var backgroundTap: UITapGestureRecognizer = {
let tap = UITapGestureRecognizer(target: self, action: #selector(touchBackground))
tap.numberOfTapsRequired = 1
tap.numberOfTouchesRequired = 1
return tap
}()
private lazy var pageControl: UIPageControl = {
let ScreenWidth = UIScreen.main.bounds.width
let ScreenHeight = UIScreen.main.bounds.height
let control = UIPageControl(frame: CGRect(x: 0, y: ScreenHeight - 30, width: ScreenWidth, height: 12))
control.backgroundColor = .clear
return control
}()
private var imageModels: [ImageBrowserModel] = [] {
didSet {
refreshPageControl()
mainCollectionView.reloadData()
}
}
private var initIndex: Int?
public init(imageModels: [ImageBrowserModel], selectIndex: Int? = nil) {
super.init(nibName: nil, bundle: nil)
self.imageModels = imageModels
self.initIndex = selectIndex
self.refreshPageControl()
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override open var prefersStatusBarHidden: Bool {
return true
}
override open func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
initView()
}
}
// MARK: - 私有方法
private extension ImageBrowserController {
func initView() {
view.addSubview(mainCollectionView)
view.addSubview(pageControl)
view.addGestureRecognizer(backgroundTap)
if let index = initIndex, index < imageModels.count {
pageControl.currentPage = index
let offX = UIScreen.main.bounds.width * CGFloat(index)
mainCollectionView.setContentOffset(CGPoint(x: offX, y: 0), animated: false)
initIndex = nil
}
}
@objc func touchBackground() {
dismiss(animated: true)
}
func refreshPageControl() {
if imageModels.count > 1 {
pageControl.numberOfPages = imageModels.count
pageControl.currentPage = 0
pageControl.isHidden = false
} else {
pageControl.isHidden = true
}
}
}
// MARK: - 协议
extension ImageBrowserController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageModels.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageBrowserCell", for: indexPath) as! ImageBrowserCell
cell.show(model: imageModels[indexPath.row])
backgroundTap.require(toFail: cell.doubleTap)
return cell
}
}
extension ImageBrowserController: UIScrollViewDelegate {
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let page = Int(scrollView.contentOffset.x / scrollView.bounds.width)
pageControl.currentPage = page
}
}
Extension
public extension UIViewController {
func presentImageBrowser(imageModels: [ImageBrowserModel], selectIndex: Int? = nil) {
let imageBrowserController = ImageBrowserController(imageModels: imageModels, selectIndex: selectIndex)
present(imageBrowserController, animated: true)
}
func presentImageBrowser(imageUrls: [String], placeholder: UIImage? = nil, selectIndex: Int? = nil) {
let imageModels = imageUrls.compactMap { url -> ImageBrowserModel in
return ImageBrowserModel(url: url, placeholder: placeholder)
}
presentImageBrowser(imageModels: imageModels, selectIndex: selectIndex)
}
}
使用
let imageUrls: [String] = [
"http://b-ssl.duitang.com/uploads/item/201510/04/20151004080802_nTJYz.jpeg",
"http://b-ssl.duitang.com/uploads/item/201612/10/20161210110010_cwsxT.jpeg",
"http://g.hiphotos.baidu.com/image/pic/item/4e4a20a4462309f7e6a224cf780e0cf3d6cad61a.jpg"
]
presentImageBrowser(imageUrls: imageUrls)
查看demo