Swift-單圖瀏覽器(一行代碼即可)

工具不行 只能這樣了 我去

未命名.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)
        }
        
    }
}

Dome

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蚁趁,隨后出現(xiàn)的幾起案子筷黔,更是在濱河造成了極大的恐慌辽幌,老刑警劉巖涌攻,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件山橄,死亡現(xiàn)場離奇詭異墙歪,居然都是意外死亡听系,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門虹菲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靠胜,“玉大人,你說我怎么就攤上這事毕源±四” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵霎褐,是天一觀的道長址愿。 經常有香客問我,道長冻璃,這世上最難降的妖魔是什么响谓? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮省艳,結果婚禮上娘纷,老公的妹妹穿的比我還像新娘。我一直安慰自己跋炕,他們只是感情好赖晶,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辐烂,像睡著了一般遏插。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上棉圈,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天涩堤,我揣著相機與錄音,去河邊找鬼分瘾。 笑死胎围,一個胖子當著我的面吹牛吁系,可吹牛的內容都是我干的。 我是一名探鬼主播白魂,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼汽纤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了福荸?” 一聲冷哼從身側響起蕴坪,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敬锐,沒想到半個月后背传,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡台夺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年径玖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片颤介。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡梳星,死狀恐怖,靈堂內的尸體忽然破棺而出滚朵,到底是詐尸還是另有隱情冤灾,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布辕近,位于F島的核電站韵吨,受9級特大地震影響,放射性物質發(fā)生泄漏移宅。R本人自食惡果不足惜学赛,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吞杭。 院中可真熱鬧,春花似錦变丧、人聲如沸芽狗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽童擎。三九已至,卻和暖如春攻晒,著一層夾襖步出監(jiān)牢的瞬間顾复,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工鲁捏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芯砸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像假丧,于是被迫代替她去往敵國和親双揪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容

  • 1包帚、通過CocoaPods安裝項目名稱項目信息 AFNetworking網絡請求組件 FMDB本地數據庫組件 SD...
    陽明先生_X自主閱讀 15,980評論 3 119
  • 今天看到朋友圈里曬出的各種游玩和回家的照片渔期,我才意識到今天已經是五一假期的第一天了。今天我和女朋友都沒能得到休假渴邦,...
    MosquitoSwallow閱讀 328評論 0 0
  • 剛剛整理出提綱疯趟,犯困了,效率比預計的要慢一些谋梭。從昨天到今晚信峻,經歷了三個環(huán)節(jié)。 一是收集素材章蚣。先找到會議的方案站欺,了解...
    池淺笑安然閱讀 386評論 0 1
  • 一步一步趟過回憶的河, 擁擠又私密的花朵在路旁紛紛萎落纤垂, 令人窒息的陳年的氣息矾策, 你的活波的唇, 漸漸地無話可說峭沦。...
    南雪_閱讀 153評論 0 3