工具不行 只能這樣了 我去
未命名.gif
調用
只要告訴當前控制器 和 即將放大的UIImageView 即可
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
HWImageBrowse.showView(imageView: imageView)
}
實現(xiàn)原理
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<UITouch>, 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通知系統(tǒng)動畫執(zhí)行完畢
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通知系統(tǒng)動畫執(zhí)行完畢
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)
}
}
}