用Swift写朋友圈图片浏览器

现在网上好的swift图片浏览器几乎没有,于是我就写了一个swift的图片浏览器,适配不同尺寸图片,支持image url 和 PHAssert.只依赖于SDWebImage这一个第三方框架,效果如下

图片浏览器.gif

github demo下载链接

图片浏览器有两个难点

  1. 从起始图片位置渐进转场动画到浏览器,浏览器返回消失到指定图片位置.
  2. 开始图片列表里的图片都是统一尺寸,但是大图显示都是按图片原始宽高等比例显示.渐变过程要稳定变化.

图片固定宽高显示模式,一般图片列表里用

固定尺寸显示.png

先看看图片常用的几种显示形式

图片显示.png

图片等比例缩放显示模式,一般图片列表里用,我用的图片有三种尺寸

按宽高等比例显示.png
两种尺寸图片.png

项目文件结构

屏幕快照 2017-04-14 17.31.59.png

我的浏览器的用法,在点击图片的方法里调用

    //selectIndex: 当前点击的图片在所有图片中的顺序 从0开始, images: 放有url字符串的数组
    let photoB = PhotoBrowser(selectIndex: backImageVi.tag - kbaseTag, images: imageArray)
    //点击的那个imageView告诉浏览四
    photoB.sourceImageView = imageViArray[backImageVi.tag - kbaseTag]
    //传回当前浏览器图片索引
    photoB.endPageIndexClosure = {[weak self] (index: Int) in
        //你根据返回索引告诉浏览器动画返回到哪一个ImageView上
        photoB.endImageView = self?.imageViArray[index]
    }
    self.present(photoB, animated: true, completion: nil)

下面我说一下这个浏览器的实现
我用UICollectionView实现,列表里面图片全是等宽高,多余的裁掉.

浏览器主控制器 PhotoBrowser

import UIKit
import Photos

let jdkresuId = "kJDPhotoBrowserId"

class JDPhotoBrowser: UIViewController {

var imageRectDict: [IndexPath: CGRect] = [IndexPath: CGRect]()


var isViewAppeared: Bool = false

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    isViewAppeared = true
}

enum imageSourceType {
    case image
    case url
    case asserts
}
///图片的url字符串数组
var urls:[String]?
var images: [UIImage]?
var asserts: [PHAsset]?

//传回当前浏览器图片索引
var endPageIndexClosure: (( _ index: Int)->())?
var imageSourceTp: imageSourceType = .image
var deleteButtonClosure: (( _ index: Int)->())?  //点击删除按钮时index
private lazy var indexLabel = UILabel()

var sourceImageView: UIImageView?{
    didSet{
        photoBrowserAnimator.sourceImageView = sourceImageView
        photoBrowserAnimator.endImageView = sourceImageView
        photoBrowserAnimator.superVc = self
    }
} // 来源view
var endImageView: UIImageView?{
    didSet{
        photoBrowserAnimator.endImageView = endImageView
    }
} // 消失时候imageview


var lastPage: Int = 0
///静止后选中照片的索引
var currentPage : Int?{
    didSet{
        if self.imageSourceTp == .image {
            guard let kcount  = images?.count else { return  }
            indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
        }else if self.imageSourceTp == .url{
            guard let kcount  = urls?.count else { return  }
            indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
        }else if self.imageSourceTp == .asserts{
            guard let kcount  = asserts?.count else { return  }
            indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
        }

        
    }
}

//1 url
init(selectIndex: Int, urls: [String]) {
    super.init(nibName: nil, bundle: nil)
    self.currentPage = selectIndex
    self.urls = urls
    self.imageSourceTp = .url
    self.modalPresentationStyle = .custom
    self.transitioningDelegate = photoBrowserAnimator
}

//2 image 第一个0
init(selectIndex: Int, images: [UIImage]) {
    super.init(nibName: nil, bundle: nil)
    self.currentPage = selectIndex
    self.images = images
    self.imageSourceTp = .image
    self.modalPresentationStyle = .custom
    self.transitioningDelegate = photoBrowserAnimator
}

//3 相册
init(selectIndex: Int, asserts: [PHAsset]) {
    super.init(nibName: nil, bundle: nil)
    self.currentPage = selectIndex

    self.asserts = asserts
    self.imageSourceTp = .asserts
    self.modalPresentationStyle = .custom
    self.transitioningDelegate = photoBrowserAnimator
}

lazy var collectionView: UICollectionView = {

    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: kJDScreenWidth , height: kJDScreenHeight )
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    layout.scrollDirection = .horizontal
    
    let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: kJDScreenWidth, height: kJDScreenHeight ), collectionViewLayout: layout)
    collectionView.register(JDPhotoBrowserCell.self, forCellWithReuseIdentifier: jdkresuId)
    collectionView.delegate = self;
    collectionView.dataSource = self;
    collectionView.backgroundColor = UIColor.black
    collectionView.isPagingEnabled = true
    collectionView.showsHorizontalScrollIndicator = false
    collectionView.alwaysBounceHorizontal = true
    return collectionView
}()

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.black
    self.view.addSubview(collectionView)
    let indexPath = IndexPath(item: (currentPage ?? 0), section: 0)

    DispatchQueue.main.async {
        if indexPath.row <= ((self.images?.count ?? 0) - 1) || indexPath.row <= ((self.urls?.count ?? 0) - 1) || indexPath.row <= ((self.asserts?.count ?? 0) - 1){
        
        self.collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
        }
    }
    
    photoBrowserAnimator.currentPage = (currentPage ?? 0)
    
    deleteBtn.frame = CGRect(x: kJDScreenWidth - 45, y: 30, width: 30, height: 30)
    deleteBtn.setBackgroundImage(UIImage(named: "delete"), for: .normal)

// self.view.addSubview(deleteBtn)
// deleteBtn.addTarget(self, action: #selector(delete(btn:)), for: .touchUpInside)

    self.view.addSubview(indexLabel)
    indexLabel.backgroundColor = UIColor.black
    indexLabel.textColor = UIColor.white
    indexLabel.textAlignment = .center
    indexLabel.frame = CGRect(x: 0, y: kJDScreenHeight - 40, width: 80, height: 30)
    indexLabel.centerX = kJDScreenWidth * 0.5

// saveBtn.frame = CGRect(x: kJDScreenWidth - 80, y: indexLabel.y, width: 50, height: 50)
// saveBtn.addTarget(self, action: #selector(saveImg), for: .touchUpInside)
// self.view.addSubview(saveBtn)

    if  self.imageSourceTp == .image{
        guard let kcount  = images?.count else { return  }
        indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
     }else if  self.imageSourceTp == .url{
        guard let kcount  = urls?.count else { return  }
        indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
    }else if  self.imageSourceTp == .asserts{
        guard let kcount  = asserts?.count else { return  }
        indexLabel.text = "\((currentPage ?? 0) + 1)/\(kcount)"
    }
}

//删除
@objc private func delete(btn: UIButton){
    if deleteButtonClosure != nil {
        deleteButtonClosure?((currentPage ?? 0))
    }
}

//--------懒加载--------
fileprivate lazy var photoBrowserAnimator : JDPhotoBrowserAnimator = JDPhotoBrowserAnimator()
private lazy var deleteBtn : UIButton = {
    let btn: UIButton = UIButton()
    btn.setTitleColor(UIColor.red, for: .normal)
    btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
    return btn
}()

private lazy var saveBtn : UIButton = {
    let btn: UIButton = UIButton()
    btn.size = CGSize(width: 50, height: 50)
    btn.setBackGroundColor(color: UIColor.red, type: .normal)
    btn.setTitleColor(UIColor.red, for: .normal)
    btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
    return btn
}()

// @objc private func saveImg(){
// let indexPath = IndexPath(item: (currentPage ?? 0), section: 0)
// let cell = self.collectionView.cellForItem(at: indexPath) as! JDPhotoBrowserCell
//
// self.saveImageToPhotoAlbum1(saveImage: cell.backImg.image!)
// }
//
// //保存照片
// func saveImageToPhotoAlbum1(saveImage: UIImage){
// UIImageWriteToSavedPhotosAlbum(saveImage, self, #selector(saveImageToo(image:didFinishSavingWithError:contextInfo:)), nil)
// }
//
// func saveImageToo(image:UIImage,didFinishSavingWithError error:NSError?,contextInfo:AnyObject) {
// if error != nil {
// return
// } else {
// // SVProgressHUD.showSuccess(withStatus: "保存成功")
// }
//
//
// }

}

extension JDPhotoBrowser :UICollectionViewDelegate,UICollectionViewDataSource{

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {

    if self.imageSourceTp == .image {
        return (self.images?.count)!
    }else if self.imageSourceTp == .url{
        return (self.urls?.count)!
    }else {
        return (self.asserts?.count)!
    }
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
   
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: jdkresuId, for: indexPath as IndexPath) as! JDPhotoBrowserCell
    cell.scrollView.setZoomScale(1, animated: false)

    
    if self.imageSourceTp == .image {
        cell.image = self.images?[indexPath.item]
    }else if self.imageSourceTp == .url{
        cell.imageUrl = self.urls?[indexPath.item]
    }else if self.imageSourceTp == .asserts{
        cell.assert = self.asserts?[indexPath.item]

    }
    
    
    cell.cellPhotoBrowserAnimator = photoBrowserAnimator

    return cell
}


func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    self.dismiss(animated: true, completion: nil)
}

func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    currentPage = Int(scrollView.contentOffset.x / scrollView.width)
    lastPage = currentPage!
    photoBrowserAnimator.currentPage = currentPage ?? 0
    
            
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView){
    

    if self.endPageIndexClosure != nil {
        endPageIndexClosure?(currentPage ?? 0)
    }
    
}

}

单一图片父控件类

import UIKit
import Photos
import SDWebImage

class JDPhotoBrowserCell: UICollectionViewCell,UIGestureRecognizerDelegate ,UIScrollViewDelegate{

var imageRect = CGRect(x: 0 , y:0, width: kJDScreenWidth  , height:  kJDScreenHeight )


var isDissmiss: Bool = false
var totalScale : CGFloat = 1.0
var maxScale : CGFloat = 5.0
var minScale : CGFloat = 1
var isImageDone: Bool = false
var cellPhotoBrowserAnimator : JDPhotoBrowserAnimator?

var image: UIImage?{
    didSet{
        backImg.image = image
        self.getImageSize(image: image!)
    }
}


var lastImageId: Int32 = 0

var assert: PHAsset?{
    didSet{
        
        if assert != nil {
            
            self.getOrangeImage(asset: assert!) {[weak self] (data) in
                
                let img = UIImage(data: data!)
                if data != nil {
                    
                    self?.backImg.image = img
                    self?.getImageSize(image: (self?.backImg.image)!)
                }
            }
            
            
        }
        
        
    }
}


var imageUrl: String?{
    didSet{
        
        
        self.cellPhotoBrowserAnimator?.isImageDone = false
        self.isImageDone = false
        
        self.backImg.sd_setImage(with: URL(string: imageUrl!), placeholderImage: placeImage, options: .progressiveDownload, progress: { (receive, all, _) in
            
        }) { (image, _, _, _) in
            
            self.getImageSize(image: image!)
        }
        
    }
}

typealias ImgCallBackType = (Data?)->()

//获取原图
private func getOrangeImage(asset: PHAsset,callback: @escaping ImgCallBackType){
    //获取原图
    
    let option = PHImageRequestOptions()
    option.isSynchronous = true
    option.resizeMode = .exact
    
    lastImageId = PHImageManager.default().requestImageData(for: asset, options: option, resultHandler: { (data, string, up, nil) in
        if data != nil{
            callback(data)
        }
        
    })
    
    
    
}

//大图尺寸
func getImageSize(image: UIImage){
    
    self.isImageDone = true
    self.cellPhotoBrowserAnimator?.isImageDone = true
    
    let imageSize = image.size
    let imageW = imageSize.width
    let imageH = imageSize.height
    let actualImageW = kJDScreenWidth
    let actualImageH = actualImageW/imageW * imageH
    
    
    imageRect = CGRect(x: 0, y: (kJDScreenHeight - actualImageH)/2, width: actualImageW, height: actualImageH)
    
    if actualImageH > kJDScreenHeight {
        imageRect = CGRect(x: 0, y: 0, width: kJDScreenWidth, height: kJDScreenHeight)
    }
    
    
    self.scrollView.contentSize = CGSize(width: imageRect.size.width, height: imageRect.size.height)
    
    self.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    
    self.scrollView.contentInset = UIEdgeInsets(top: imageRect.origin.y, left: 0, bottom: 0, right: 0)
    
    backImg.frame = CGRect(x: 0, y: 0, width: imageRect.size.width, height: imageRect.size.height)
    
    backImg.layoutIfNeeded()
    scrollView.layoutIfNeeded()
}

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.black
    self.contentView.addSubview(scrollView)
    
    scrollView.addSubview(backImg)
    
    scrollView.delegate = self
    addGesture()
}

private func addGesture(){
    //单击
    let tap = UITapGestureRecognizer(target: self, action: #selector(backImgTap1(recognizer:)))
    tap.numberOfTouchesRequired = 1
    tap.numberOfTapsRequired = 1
    tap.delegate = self
    backImg.addGestureRecognizer(tap)
    
    self.scrollView.addGestureRecognizer(tap)
    
    //双击
    let tap2 = UITapGestureRecognizer(target: self, action: #selector(backImgTap2(recognizer:)))
    tap2.numberOfTapsRequired = 2
    tap2.numberOfTouchesRequired = 1
    tap2.delegate = self
    backImg.addGestureRecognizer(tap2)
    tap.require(toFail: tap2)
    self.scrollView.addGestureRecognizer(tap2)
    
    
    //啮合手势
    let pinch = UIPinchGestureRecognizer(target: self, action: #selector(pinchDid(recognizer:)))
    pinch.delegate = self
    backImg.addGestureRecognizer(pinch)
    
    //拖拽
    let pan = UIPanGestureRecognizer(target: self, action: #selector(panDid(recognizer:)))
    pan.maximumNumberOfTouches = 1  //一个手指拖动
    pan.delegate = self
    backImg.addGestureRecognizer(pan)
}


//拖拽
@objc private func panDid(recognizer:UIPanGestureRecognizer) {
    let backImageVi = recognizer.view as! UIImageView
    let point = recognizer.translation(in: self.contentView)
    backImageVi.transform.translatedBy(x: point.x, y: point.y)
    recognizer.setTranslation(CGPoint(x: 0, y: 0), in: backImageVi)
}

//单击
@objc private func backImgTap1(recognizer: UITapGestureRecognizer){
    let fatherVc = self.backImg.getCurrentVc() as! JDPhotoBrowser
    fatherVc.dismiss(animated: true, completion: nil)
}

//双击
@objc private func backImgTap2(recognizer: UITapGestureRecognizer){
    let backImageVi = self.backImg
    let touchPoint = recognizer.location(in: backImageVi)
    
    
    UIView.animate(withDuration: 0.25) {
        if backImageVi.width > self.imageRect.width{//缩小
            self.scrollView.contentInset = UIEdgeInsets(top: self.imageRect.origin.y, left: 0, bottom: 0, right: 0)
            
            
            let zoomRect = self.zoomRectFor(scale: 1, center: touchPoint)
            self.scrollView.zoom(to:zoomRect, animated: true)
            
            self.scrollView.layoutIfNeeded()
        }else{//放大
            let bili = kJDScreenHeight/self.imageRect.height
            //            print("bili",bili)
            if bili > 2{
                let zoomRect = self.zoomRectFor(scale: bili, center: touchPoint)
                self.scrollView.zoom(to:zoomRect, animated: true)
                
            }else{
                let  zoomRect1 = self.zoomRectFor(scale: 2, center: touchPoint)
                self.scrollView.zoom(to:zoomRect1, animated: true)
                
            }
            
            self.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
            
            
            self.scrollView.layoutIfNeeded()
        }
    }
}

//捏合
@objc private func pinchDid(recognizer: UIPinchGestureRecognizer){
    self.scrollView.contentInset = UIEdgeInsets(top: self.imageRect.origin.y, left: 0, bottom: 0, right: 0)
    
    let scale = recognizer.scale
    self.totalScale *= scale
    recognizer.scale = 1.0;
    
    if totalScale > maxScale {
        return
    }
    if totalScale < minScale{
        return
    }
    
    self.scrollView.setZoomScale(totalScale, animated: true)
    
    self.scrollView.layoutIfNeeded()
}

func zoomRectFor(scale: CGFloat,center: CGPoint) -> CGRect{
    let imgW = imageRect.size.width
    let imgH = imageRect.size.height
    var zoomRect: CGRect = CGRect(x: 0, y: 0, width: 0, height: 0)
    zoomRect.size.height = imgH / scale
    zoomRect.size.width  = imgW / scale
    zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0)
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0)
    return zoomRect;
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


//允许多个手势存在
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool{
    
    return true
}

func scrollViewDidScroll(_ scrollView: UIScrollView){
}


// 告诉scrollview要缩放的是哪个子控件
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return self.backImg
}

func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
    if totalScale >= maxScale {
        totalScale = maxScale
    }else if totalScale < minScale{
        totalScale = minScale
    }
}


// ------懒加载------
lazy var backImg : UIImageView = {
    var img = UIImageView()
    img.isUserInteractionEnabled = true
    img.contentMode = .scaleAspectFit
    img.frame = CGRect(x: 0, y: 0, width: kJDScreenWidth , height: kJDScreenHeight )
    img.backgroundColor = UIColor.black
    return img
}()

lazy var scrollView: UIScrollView = {
    let scrollView = UIScrollView()
    scrollView.backgroundColor = UIColor.black
    scrollView.minimumZoomScale = 1;
    scrollView.maximumZoomScale = 5;
    
    scrollView.frame = CGRect(x: 0, y: 0, width: kJDScreenWidth, height: kJDScreenHeight)
    scrollView.contentSize = CGSize(width: kJDScreenWidth, height: kJDScreenHeight)
    
    scrollView.isUserInteractionEnabled = true
    scrollView.setZoomScale(1, animated: false)
    scrollView.alwaysBounceHorizontal = true
    return scrollView
}()

lazy var  placeImage: UIImage = {
    let image = UIImage(named: "blackall")
    
    return image!
}()

}

由于图片前后两种显示模式,不处理好的话会出现下面的问题

图片浏览器2.gif

自定义转场动画类

import UIKit

class JDPhotoBrowserAnimator: NSObject {

var imageRect = CGRect(x: 0 , y:0, width: kJDScreenWidth  , height:  kJDScreenHeight )

var isPresented : Bool = false
var sourceImageView: UIImageView? // 来源view
var endImageView: UIImageView? // 消失时候view
var currentPage: Int = 0
var preSnapView : UIView?
var isAniDone : Bool = false

var superVc: JDPhotoBrowser?


//加载进度提示框
private lazy var progressView : UIActivityIndicatorView = {
    let loadVi = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.whiteLarge)
    loadVi.startAnimating()
    return loadVi
}()

var isImageDone: Bool?{
    didSet{
        if isImageDone == true && self.isAniDone == true{
            progressView.removeFromSuperview()
            self.preSnapView?.removeFromSuperview()
        }else{
            if self.isAniDone == true {
                progressView.center = CGPoint(x: imageRect.size.width/2, y: imageRect.size.height/2)
                self.preSnapView?.addSubview(progressView)
                //  print("加载中")
            }
        }
    }
}

}

extension JDPhotoBrowserAnimator : UIViewControllerTransitioningDelegate{
// isPresented 调用的动画
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresented = true
return self
}

//消失时候调用的动画
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    isPresented = false
    return self
}

}

extension JDPhotoBrowserAnimator : UIViewControllerAnimatedTransitioning{
//动画时间
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
//动画方式
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

    isPresented ? animationForPresentedView(transitionContext) : animationForDismissView(transitionContext)
}

//弹出动画
func animationForPresentedView(_ transitionContext: UIViewControllerContextTransitioning){
    
    //取出下一个 view 浏览器
    let presentedView = transitionContext.view(forKey: UITransitionContextViewKey.to)!
    transitionContext.containerView.addSubview(presentedView)
    
    if sourceImageView == nil {
        transitionContext.completeTransition(true)
        return
    }
    
    let imgView = UIImageView()
    imgView.image = sourceImageView?.image
    //        imgView.frame = (sourceImageView?.frame)!
    
    let window = UIApplication.shared.keyWindow
    imgView.frame = (sourceImageView?.convert((sourceImageView?.bounds)!, to: window))!
    
    self.getImageSize()
    
    let imgSize = imgView.image?.size
    let imgW = imgSize?.width
    let imgH = imgSize?.height
    imgView.width = (sourceImageView?.width)!
    imgView.height = (sourceImageView?.width)!/imgW! * imgH!
    let snapView = imgView.snapshotView(afterScreenUpdates: true)
    
    //截图
    
    snapView?.frame = imgView.frame
    transitionContext.containerView.addSubview(snapView!)
    
    presentedView.alpha = 0.0
    transitionContext.containerView.backgroundColor = UIColor.black
    
    let tap = UITapGestureRecognizer(target: self, action: #selector(snapViewTap(recognizer:)))
    tap.numberOfTouchesRequired = 1
    tap.numberOfTapsRequired = 1
    snapView?.addGestureRecognizer(tap)
    
    self.preSnapView = snapView
    self.isAniDone = false
    UIView.animate(withDuration:0.3 , animations: {
        snapView?.frame = self.imageRect
        
    }, completion: { (_) in
        self.isAniDone = true
        
        let presentedVc = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! JDPhotoBrowser
        let indexPath = IndexPath(item: self.currentPage, section: 0)
        guard  presentedVc.collectionView.cellForItem(at: indexPath) != nil else { return }
        let cell = presentedVc.collectionView.cellForItem(at: indexPath) as! JDPhotoBrowserCell
        
        
        self.isImageDone = cell.isImageDone
        
        presentedView.alpha = 1.0
        transitionContext.containerView.backgroundColor = UIColor.clear
        transitionContext.completeTransition(true)
    })
}

//单击
@objc private func snapViewTap(recognizer: UITapGestureRecognizer){
    self.superVc?.dismiss(animated: true, completion: nil)
}

//大图尺寸
func getImageSize(){
    let imageSize = sourceImageView?.image?.size
    let imageW = imageSize?.width
    let imageH = imageSize?.height
    let actualImageW = kJDScreenWidth
    let actualImageH = actualImageW/imageW! * imageH!
    imageRect = CGRect(x: 0, y: (kJDScreenHeight - actualImageH)/2, width: actualImageW, height: actualImageH)
}



//消失动画
func animationForDismissView(_ transitionContext: UIViewControllerContextTransitioning){
    
    //上一级view
    let dismissView = transitionContext.view(forKey: UITransitionContextViewKey.from)!
    let dismissVc = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! JDPhotoBrowser
    
    
    let indexPath = IndexPath(item: currentPage, section: 0)
    
    if dismissVc.collectionView.cellForItem(at: indexPath) == nil {
        //currentPage快速滑动一直不变 最后销毁了
        transitionContext.completeTransition(true)
        
        return
    }
    
    let cell = dismissVc.collectionView.cellForItem(at: indexPath) as! JDPhotoBrowserCell
    
    let snapView = cell.backImg.snapshotView(afterScreenUpdates: true)
    
    
    snapView?.frame = imageRect
    transitionContext.containerView.addSubview(snapView!)
    dismissView.removeFromSuperview()
    
    UIView.animate(withDuration: 0.3, animations: {
        if self.endImageView == nil{
            snapView?.frame = self.imageRect
        }else{
            
            var theFrame: CGRect = (self.endImageView?.convert((self.endImageView?.bounds)!, to: self.endImageView?.getCurrentVc()?.view))!
            
            //根据导航栏是不是透明的来做
            if self.endImageView?.getCurrentVc()?.navigationController != nil && self.endImageView?.getCurrentVc()?.navigationController?.navigationBar.isTranslucent == false{
                theFrame = CGRect(x: theFrame.origin.x, y: theFrame.origin.y + 64, width: theFrame.size.width, height: theFrame.size.height)
            }
            
            snapView?.frame = theFrame
        }
    }, completion: { (_) in
        snapView?.removeFromSuperview()
        transitionContext.completeTransition(true)
        
    })
    
}
}  } }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • 概述 摘要:从制作一个看图app和了解关键概念开始swift编程。 概念:Constants and variab...
    lbhw阅读 454评论 0 1
  • swift实现图片浏览器 1.配置环境 2.搭建首页home界面 3.自定义流水布局注意重写prepareLayo...
    亡灵诅咒阅读 2,290评论 1 2
  • 主要内容:实现自定义转场动画 大家平常用微信,微博的过程中肯定都有查看过朋友圈和微博所发布的照片,当点击九宫格的某...
    DHai阅读 1,138评论 1 1
  • 自定义转场动画 相对于OC来说,在Swift中编写iOS的转场动画要显得更为简单 我们在这里模拟一个场景:"col...
    S_Lyu阅读 1,292评论 0 5
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62