Swift-单图浏览器(一行代码即可)

工具不行 只能这样了 我去

Swift-单图浏览器(一行代码即可)_第1张图片
未命名.gif

调用

只要告诉当前控制器 和 即将放大的UIImageView 即可

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
       HWImageBrowse.showView(imageView: imageView)
    }

实现原理

import UIKit

class HWImageBrowse: UIViewController {
    
    private let customTransition = HWImageBrowseCustomTransition()
    private var imageView = UIImageView.init()
    private var _image : UIImage?
    var image : UIImage? {
        set {
            _image = newValue
            if newValue == nil {return}
            view.addSubview(imageView)
            imageView.frame = getFullScreenImageRectWithImage(image: newValue!)
            imageView.image = newValue
        }
        get {
            return _image
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        self.transitioningDelegate = customTransition
        view.backgroundColor = UIColor.black
    }

    /// 快速显示 imageView 必传
    class func showView(formVC:UIViewController? = nil ,imageView:UIImageView) {
        let vc = HWImageBrowse()
        vc.image = imageView.image
        vc.customTransition.setTransitionImageView(imageView)
        if formVC == nil {
            UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true) {}
        } else {
            formVC!.present(vc, animated: true) {}
        }
    }
    override func touchesBegan(_ touches: Set, with event: UIEvent?) {
        self.dismiss(animated: true) {}
    }
    func getFullScreenImageRectWithImage(image:UIImage) -> CGRect {
        let size: CGSize = image.size
        let scaleX: CGFloat = UIScreen.main.bounds.size.width / size.width
        let scaleY: CGFloat = UIScreen.main.bounds.size.height / size.height
        if scaleX > scaleY {
            let width: CGFloat = size.width * scaleY
            return CGRect(x: UIScreen.main.bounds.size.width / 2.0 - width / 2.0, y: 0.0, width: width, height: UIScreen.main.bounds.size.height)
        } else {
            let height: CGFloat = size.height * scaleX
            return CGRect(x: 0, y: UIScreen.main.bounds.size.height / 2.0 - height / 2.0, width: UIScreen.main.bounds.size.width, height: height)
        } 
    }
}

class HWImageBrowseCustomTransition: NSObject,UIViewControllerTransitioningDelegate {
    
    private var animationStartFrame : CGRect = CGRect.zero
    private var transitionImage : UIImage?
    private lazy var interactiveAnimator : UIPercentDrivenInteractiveTransition = {
        let interactiveAnimator = UIPercentDrivenInteractiveTransition()
        return interactiveAnimator
    }()
    
    func setTransitionImageView(_ transitionImageView:UIImageView) {
        animationStartFrame = (transitionImageView.superview?.convert(transitionImageView.frame, to: (UIApplication.shared.delegate?.window)!))!
        transitionImage = transitionImageView.image
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        let animator = HWImageBrowseDismissAnimator()
        animator.endFrame = animationStartFrame
        animator.transitionImage = transitionImage
        return animator
    }
    
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        let animator = HWImageBrowsePresentAnimator()
        animator.startFrame = animationStartFrame
        animator.transitionImage = transitionImage
        return animator
    }
    
    func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return self.interactiveAnimator
    }
    
    func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        return self.interactiveAnimator
    }
    
    func finishInteractiveTransition() {
        self.interactiveAnimator.finish()
    }
    
    func cancelInteractiveTransition() {
        self.interactiveAnimator.cancel()
    }
    
    func updateInteractiveTransition(percentComplete:CGFloat) {
        self.interactiveAnimator.update(percentComplete)
    }
    
}

class HWImageBrowseDismissAnimator: NSObject,UIViewControllerAnimatedTransitioning {
    var transitionImage : UIImage?
    var endFrame : CGRect = CGRect.zero
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.5
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        //转场过渡的容器view
        let containerView: UIView? = transitionContext.containerView
        //ToVC
        let toViewController: UIViewController? = transitionContext.viewController(forKey: .to)
        let toView: UIView = (toViewController?.view)!
        containerView?.addSubview(toView)
        //图片背景的空白view (设置和控制器的背景颜色一样,给人一种图片被调走的假象)
        let imgBgWhiteView = UIView(frame: endFrame)
        imgBgWhiteView.backgroundColor = UIColor.white
        containerView?.addSubview(imgBgWhiteView)
        //有渐变的黑色背景
        let bgView = UIView(frame: containerView?.bounds ?? CGRect.zero)
        bgView.backgroundColor = UIColor.black
        bgView.alpha = 1
        containerView?.addSubview(bgView)
        
        
        //过渡的图片
        let transitionImgView = UIImageView()
        transitionImgView.frame = getFullScreenImageRectWithImage(image: transitionImage!)
        transitionImgView.contentMode = .scaleAspectFill
        transitionImgView.clipsToBounds = true
        transitionImgView.image = transitionImage
        transitionContext.containerView.addSubview(transitionImgView)
        UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
            transitionImgView.frame = self.endFrame
            bgView.alpha = 0
        }) { finished in
            let wasCancelled: Bool = transitionContext.transitionWasCancelled
            imgBgWhiteView.removeFromSuperview()
            bgView.removeFromSuperview()
            transitionImgView.removeFromSuperview()
            //设置transitionContext通知系统动画执行完毕
            transitionContext.completeTransition(!wasCancelled)
        }
        
        
    }
    func getFullScreenImageRectWithImage(image:UIImage) -> CGRect {
        let size: CGSize = image.size
        let scaleX: CGFloat = UIScreen.main.bounds.size.width / size.width
        let scaleY: CGFloat = UIScreen.main.bounds.size.height / size.height
        if scaleX > scaleY {
            let width: CGFloat = size.width * scaleY
            return CGRect(x: UIScreen.main.bounds.size.width / 2.0 - width / 2.0, y: 0.0, width: width, height: UIScreen.main.bounds.size.height)
        } else {
            let height: CGFloat = size.height * scaleX
            return CGRect(x: 0, y: UIScreen.main.bounds.size.height / 2.0 - height / 2.0, width: UIScreen.main.bounds.size.width, height: height)
        }
    }
}

class HWImageBrowsePresentAnimator: NSObject,UIViewControllerAnimatedTransitioning {
    var transitionImage : UIImage?
    var startFrame : CGRect = CGRect.zero
    
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.5
    }
    
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        // 转场过渡动画的容器view
        
        let containerView: UIView? = transitionContext.containerView
        // fromVC
        let fromViewController: UIViewController? = transitionContext.viewController(forKey: .from)
        let fromView: UIView = (fromViewController?.view)!
        containerView?.addSubview(fromView)
        // toVC
        let toViewController: UIViewController? = transitionContext.viewController(forKey: .to)
        let toView: UIView = (toViewController?.view)!
        containerView?.addSubview(toView)
        toView.isHidden = true
        // fromVC的图片背景的空白view(设置和控制器的背景颜色一样,给人一种图片被调走的假象 [可以换种颜色看看效果])
        let imageBackground = UIView(frame: startFrame)
        imageBackground.backgroundColor = UIColor.white
        containerView?.addSubview(imageBackground)
        
        // 渐变的黑色背景
        
        let background = UIView(frame: (containerView?.bounds)!)
        background.backgroundColor = UIColor.black
        background.alpha = 0.0
        containerView?.addSubview(background)
        // 过渡的图片
        let transtionImageView = UIImageView()
        transtionImageView.frame = startFrame
        transtionImageView.contentMode = .scaleAspectFill
        transtionImageView.clipsToBounds = true
        transtionImageView.image = transitionImage
        containerView?.addSubview(transtionImageView)
        let endFrame: CGRect = getFullScreenImageRectWithImage(image: transitionImage!)
        
        UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
            transtionImageView.frame = endFrame
            background.alpha = 1
        }) { finished in
            toView.isHidden = false
            imageBackground.removeFromSuperview()
            background.removeFromSuperview()
            transtionImageView.removeFromSuperview()
            let wasCancelled: Bool = transitionContext.transitionWasCancelled
            //设置transitionContext通知系统动画执行完毕
            transitionContext.completeTransition(!wasCancelled)
        }
        
    }
    func getFullScreenImageRectWithImage(image:UIImage) -> CGRect {
        let size: CGSize = image.size
        let scaleX: CGFloat = UIScreen.main.bounds.size.width / size.width
        let scaleY: CGFloat = UIScreen.main.bounds.size.height / size.height
        if scaleX > scaleY {
            let width: CGFloat = size.width * scaleY
            return CGRect(x: UIScreen.main.bounds.size.width / 2.0 - width / 2.0, y: 0.0, width: width, height: UIScreen.main.bounds.size.height)
        } else {
            let height: CGFloat = size.height * scaleX
            return CGRect(x: 0, y: UIScreen.main.bounds.size.height / 2.0 - height / 2.0, width: UIScreen.main.bounds.size.width, height: height)
        }
        
    }
}

Dome

你可能感兴趣的:(Swift-单图浏览器(一行代码即可))