直接上代碼
首先定義一個顯示大圖的協(xié)議
protocol ShowImageProtocol {}
然后添加協(xié)議extension---
1.第一個是不帶動畫的直接模態(tài)顯示出大圖控制器界面
2.第二個是帶動畫的協(xié)議擴(kuò)展诊杆,類似于微信朋友圈顯示大圖妓灌,但是此時需要顯示的圖片所在的控制器準(zhǔn)守UIViewControllerTransitioningDelegate協(xié)議;并且為了使動畫開始frame是從所點(diǎn)擊的imageView展開顯示的率触,所以需要外界傳入一個imageView终议,用來獲取初始frame
extension ShowImageProtocol where Self: UIViewController {
/**
不帶動畫的顯示大圖
- parameter dataSource: 數(shù)據(jù)源
- parameter currentIndex: 第幾個
*/
func showImages(with dataSource: [String], currentIndex: Int) {
guard dataSource.count - 1 >= currentIndex else {
return
}
let vc = ShowImagesController(dataSource: dataSource, currentIndex: currentIndex)
vc.modalTransitionStyle = .CrossDissolve
presentViewController(vc, animated: true, completion: nil)
}
}
extension ShowImageProtocol where Self: UIViewController, Self: UIViewControllerTransitioningDelegate {
/**
帶動畫的顯示大圖---必須遵循UIViewControllerTransitioningDelegate
- parameter dataSource: 數(shù)據(jù)源
- parameter currentIndex: 第幾個
- parameter imageView: 要顯示的imageView,主要是為了獲取frame
*/
func showImages(with dataSource: [String], currentIndex: Int, delegate: ModalAnimationDelegate?) {
guard let delegate = delegate else {
fatalError("does not have delegate")
}
guard dataSource.count - 1 >= currentIndex else {
return
}
let vc = ShowImagesController(dataSource: dataSource, currentIndex: currentIndex)
vc.transitioningDelegate = delegate
vc.modalPresentationStyle = .Custom
presentViewController(vc, animated: true, completion: nil)
}
}
外界調(diào)用時,需要首先準(zhǔn)守ShowImageProtocol協(xié)議
1.不帶動畫的直接調(diào)用第一個方法即可
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = collectionView.cellForItemAtIndexPath(indexPath) as? PicCollectionViewCell else { return }
showImages(with: viewModel.dataSource, currentIndex: indexPath.item)
}
2.帶動畫的還需要準(zhǔn)守UIViewControllerTransitioningDelegate協(xié)議穴张。同時控制器設(shè)置屬性
private var delegate: ModalAnimationDelegate?
然后细燎,在需要顯示大圖的地方,先把delegate置為nil陆馁,再創(chuàng)建delegate---因?yàn)榇朔椒ㄐ枰粋€imageView屬性找颓,所以最好把屬性設(shè)置為可選,然后先置為nil叮贩,再創(chuàng)建delegate
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = collectionView.cellForItemAtIndexPath(indexPath) as? PicCollectionViewCell else { return }
delegate = nil
delegate = ModalAnimationDelegate(originalView: cell.picV)
showImages(with: viewModel.dataSource, currentIndex: indexPath.item, delegate: delegate)
}
同時
在這里有一個地方需要特別注意的---那就是顯示大圖的控制器collectionviewcell之間有間距的設(shè)置方法:
把collectionView和cell的寬設(shè)置為屏寬加固定的間距并且cell之間間距為0击狮,同時開始開啟pagingEnabled = true,當(dāng)然cell上的scrollview需距離到contentView右側(cè)邊距為我們設(shè)置的間距大小益老。
/// 滾動時彪蓬,cell所顯示的間距大小
private let cellMargin: CGFloat = 20
//這個是顯示大圖的控制器vc的初始化類方法
convenience init(dataSource: [String], currentIndex: Int) {
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: UIScreen.mainScreen().bounds.width + cellMargin, height: UIScreen.mainScreen().bounds.height)
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .Horizontal
self.init(collectionViewLayout: layout)
self.dataSource = dataSource
self.currentIndex = currentIndex
}
然后在viewDidLoad()里面設(shè)置collectionview的frame
collectionView?.frame = UIScreen.mainScreen().bounds
collectionView?.frame.size.width = UIScreen.mainScreen().bounds.size.width + cellMargin
collectionView?.alwaysBounceHorizontal = true
collectionView?.pagingEnabled = true
collectionView?.showsHorizontalScrollIndicator = false
collectionView?.registerClass(PicuterCell.self, forCellWithReuseIdentifier: reuseIdentifier)
collectionView?.scrollToItemAtIndexPath(NSIndexPath(forItem: currentIndex, inSection: 0), atScrollPosition: .Left, animated: false)
同時為了大圖需要帶有縮放功能,我們需要在cell上放置一個scrollview捺萌,然后scrollview上再放置UIimageview档冬。這里沒有使用第三方布局,而是使用代碼約束控件
private func setUpUI() {
contentView.addSubview(scrollView)
// 關(guān)閉autoresizing 不關(guān)閉否則程序崩潰
scrollView.translatesAutoresizingMaskIntoConstraints = false
let topConstraint = NSLayoutConstraint(item: scrollView, attribute: .Top, relatedBy: .Equal, toItem: contentView, attribute: .Top, multiplier: 1, constant: 0)
let leftConstraint = NSLayoutConstraint(item: scrollView, attribute: .Left, relatedBy: .Equal, toItem: contentView, attribute: .Left, multiplier: 1, constant: 0)
let bottomConstraint = NSLayoutConstraint(item: scrollView, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: scrollView, attribute: .Right, relatedBy: .Equal, toItem: contentView, attribute: .Right, multiplier: 1, constant: -cellMargin)
contentView.addConstraints([topConstraint, leftConstraint, bottomConstraint, rightConstraint])
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 3
scrollView.delegate = self
scrollView.addSubview(picV)
picV.contentMode = .ScaleAspectFit
picV.translatesAutoresizingMaskIntoConstraints = false
let centerXCon = NSLayoutConstraint(item: picV, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1, constant: 0)
let centerYCon = NSLayoutConstraint(item: picV, attribute: .CenterY, relatedBy: .Equal, toItem: scrollView, attribute: .CenterY, multiplier: 1, constant: 0)
let leftCon = NSLayoutConstraint(item: picV, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1, constant: 0)
let rightCon = NSLayoutConstraint(item: picV, attribute: .Right, relatedBy: .Equal, toItem: scrollView, attribute: .Right, multiplier: 1, constant: 0)
let heightCon = NSLayoutConstraint(item: picV, attribute: .Height, relatedBy: .Equal, toItem: scrollView, attribute: .Height, multiplier: 1, constant: 0)
scrollView.addConstraints([heightCon, leftCon, rightCon, centerYCon, centerXCon])
let tap = UITapGestureRecognizer(target: self, action: #selector(tapAction))
picV.userInteractionEnabled = true
picV.addGestureRecognizer(tap)
}
然后桃纯,我們需要在滑動到下一個cell時酷誓,使上一個cell里面的圖像復(fù)原,這里需要用到collectionview的代理方法--cell滑動消失時觸發(fā)
override func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
guard let cell = cell as? PicuterCell else {
return
}
cell.reset()
}
//這個是cell里的方法态坦,設(shè)置scrollview的縮放為1.0
func reset() {
scrollView.setZoomScale(1.0, animated: false)
}