diff --git a/Example/Demo.xcodeproj/project.pbxproj b/Example/Demo.xcodeproj/project.pbxproj index 7484db1..bbda06d 100644 --- a/Example/Demo.xcodeproj/project.pbxproj +++ b/Example/Demo.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ A6BC0BE023913C66004A4E46 /* GalleryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BC0BDF23913C66004A4E46 /* GalleryViewController.swift */; }; A6BC0BE223914239004A4E46 /* ThumbCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BC0BE123914239004A4E46 /* ThumbCell.swift */; }; A6BC0BE823915420004A4E46 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6BC0BE723915420004A4E46 /* Data.swift */; }; + A6FE4B4624EDDBAE00E9C754 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = A6FE4B4524EDDBAE00E9C754 /* README.md */; }; D303414D23CA5F17FEDDCF7B /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 10710A5B07A80798DED8269E /* Pods_Demo.framework */; }; /* End PBXBuildFile section */ @@ -39,6 +40,7 @@ A6BC0BDF23913C66004A4E46 /* GalleryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryViewController.swift; sourceTree = ""; }; A6BC0BE123914239004A4E46 /* ThumbCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbCell.swift; sourceTree = ""; }; A6BC0BE723915420004A4E46 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; }; + A6FE4B4524EDDBAE00E9C754 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../../README.md; sourceTree = ""; }; D023B1BBDAD100A2962FDC7E /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -83,6 +85,7 @@ A6BC0BC6239139F8004A4E46 /* Demo */ = { isa = PBXGroup; children = ( + A6FE4B4524EDDBAE00E9C754 /* README.md */, A6BC0BC7239139F8004A4E46 /* AppDelegate.swift */, A6BC0BD0239139F9004A4E46 /* Assets.xcassets */, A6BC0BD2239139F9004A4E46 /* LaunchScreen.storyboard */, @@ -169,6 +172,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + A6FE4B4624EDDBAE00E9C754 /* README.md in Resources */, A6BC0BD4239139F9004A4E46 /* LaunchScreen.storyboard in Resources */, A6BC0BD1239139F9004A4E46 /* Assets.xcassets in Resources */, ); diff --git a/ImageViewerTransitionPresentationManager.swift b/ImageViewerTransitionPresentationManager.swift new file mode 100644 index 0000000..8f5d2f5 --- /dev/null +++ b/ImageViewerTransitionPresentationManager.swift @@ -0,0 +1,205 @@ +// +// ImageViewerTransitionPresentationManager.swift +// ImageViewer.swift +// +// Created by Michael Henry Pantaleon on 2020/08/19. +// + +import Foundation +import UIKit + +protocol ImageViewerTransitionViewControllerConvertible { + + // The source view + var sourceView: UIImageView? { get } + + // The final view + var targetView: UIImageView? { get } +} + +final class ImageViewerTransitionPresentationAnimator:NSObject { + + let isPresenting: Bool + + init(isPresenting: Bool) { + self.isPresenting = isPresenting + super.init() + } +} + +// MARK: - UIViewControllerAnimatedTransitioning +extension ImageViewerTransitionPresentationAnimator: UIViewControllerAnimatedTransitioning { + + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) + -> TimeInterval { + return 0.3 + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + let key: UITransitionContextViewControllerKey = isPresenting ? .to : .from + guard let controller = transitionContext.viewController(forKey: key) + else { return } + + let animationDuration = transitionDuration(using: transitionContext) + + if isPresenting { + presentAnimation( + transitionView: transitionContext.containerView, + controller: controller, + duration: animationDuration) { finished in + transitionContext.completeTransition(finished) + } + + } else { + dismissAnimation( + transitionView: transitionContext.containerView, + controller: controller, + duration: animationDuration) { finished in + transitionContext.completeTransition(finished) + } + } + } + + private func createDummyImageView(frame: CGRect, image:UIImage? = nil) + -> UIImageView { + let dummyImageView:UIImageView = UIImageView(frame: frame) + dummyImageView.clipsToBounds = true + dummyImageView.contentMode = .scaleAspectFill + dummyImageView.alpha = 1.0 + dummyImageView.image = image + return dummyImageView + } + + private func presentAnimation( + transitionView:UIView, + controller: UIViewController, + duration: TimeInterval, + completed: @escaping((Bool) -> Void)) { + + guard + let transitionVC = controller as? ImageViewerTransitionViewControllerConvertible + else { return } + + let sourceView = transitionVC.sourceView + + let dummyImageView = createDummyImageView( + frame: sourceView?.frameRelativeToWindow() ?? .zero, + image: sourceView?.image) + transitionView.addSubview(dummyImageView) + + sourceView?.alpha = 0.0 + + transitionView.addSubview(controller.view) + controller.view.alpha = 0.0 + + UIView.animate(withDuration: duration, animations: { + dummyImageView.contentMode = .scaleAspectFit + dummyImageView.frame = UIScreen.main.bounds + controller.view.alpha = 1.0 + }) { finished in + dummyImageView.removeFromSuperview() + completed(finished) + } + } + + private func dismissAnimation( + transitionView:UIView, + controller: UIViewController, + duration:TimeInterval, + completed: @escaping((Bool) -> Void)) { + + guard + let transitionVC = controller as? ImageViewerTransitionViewControllerConvertible + else { return } + + let sourceView = transitionVC.sourceView + let targetView = transitionVC.targetView + + let dummyImageView = createDummyImageView( + frame: targetView?.frameRelativeToWindow() ?? UIScreen.main.bounds, + image: targetView?.image) + transitionView.addSubview(dummyImageView) + targetView?.isHidden = true + + controller.view.alpha = 1.0 + UIView.animate(withDuration: duration, animations: { + if let sourceView = sourceView { + // return to original position + dummyImageView.frame = sourceView.frameRelativeToWindow() + } else { + // just disappear + dummyImageView.alpha = 0.0 + } + controller.view.alpha = 0.0 + }) { finished in + sourceView?.alpha = 1.0 + controller.view.removeFromSuperview() + completed(finished) + } + } +} + +final class ImageViewerTransitionPresentationController: UIPresentationController { + + override var frameOfPresentedViewInContainerView: CGRect { + var frame: CGRect = .zero + frame.size = size(forChildContentContainer: presentedViewController, + withParentContainerSize: containerView!.bounds.size) + return frame + } + + override func containerViewWillLayoutSubviews() { + presentedView?.frame = frameOfPresentedViewInContainerView + } +} + +final class ImageViewerTransitionPresentationManager: NSObject { + +} + +// MARK: - UIViewControllerTransitioningDelegate +extension ImageViewerTransitionPresentationManager: UIViewControllerTransitioningDelegate { + func presentationController( + forPresented presented: UIViewController, + presenting: UIViewController?, + source: UIViewController + ) -> UIPresentationController? { + let presentationController = ImageViewerTransitionPresentationController( + presentedViewController: presented, + presenting: presenting) + return presentationController + } + + func animationController( + forPresented presented: UIViewController, + presenting: UIViewController, + source: UIViewController + ) -> UIViewControllerAnimatedTransitioning? { + + return ImageViewerTransitionPresentationAnimator(isPresenting: true) + } + + func animationController( + forDismissed dismissed: UIViewController + ) -> UIViewControllerAnimatedTransitioning? { + return ImageViewerTransitionPresentationAnimator(isPresenting: false) + } +} + +// MARK: - UIAdaptivePresentationControllerDelegate +extension ImageViewerTransitionPresentationManager: UIAdaptivePresentationControllerDelegate { + + func adaptivePresentationStyle( + for controller: UIPresentationController, + traitCollection: UITraitCollection + ) -> UIModalPresentationStyle { + return .none + } + + func presentationController( + _ controller: UIPresentationController, + viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle + ) -> UIViewController? { + return nil + } +} diff --git a/Sources/ImageCarouselViewController.swift b/Sources/ImageCarouselViewController.swift index 3badc93..d90c2ff 100644 --- a/Sources/ImageCarouselViewController.swift +++ b/Sources/ImageCarouselViewController.swift @@ -5,17 +5,31 @@ public protocol ImageDataSource:class { func imageItem(at index:Int) -> ImageItem } -public class ImageCarouselViewController:UIPageViewController { +class ImageCarouselViewController:UIPageViewController, ImageViewerTransitionViewControllerConvertible { - weak var imageDatasource:ImageDataSource? - weak var sourceView:UIImageView! + unowned var initialSourceView: UIImageView? + var sourceView: UIImageView? { + guard let vc = viewControllers?.first as? ImageViewerController else { + return nil + } + return initialIndex == vc.index ? initialSourceView : nil + } + + var targetView: UIImageView? { + guard let vc = viewControllers?.first as? ImageViewerController else { + return nil + } + return vc.imageView + } + weak var imageDatasource:ImageDataSource? + var initialIndex = 0 var theme:ImageViewerTheme = .light { didSet { navItem.leftBarButtonItem?.tintColor = theme.tintColor - backgroundView.backgroundColor = theme.color + backgroundView?.backgroundColor = theme.color } } @@ -31,37 +45,40 @@ public class ImageCarouselViewController:UIPageViewController { return _navBar }() - private(set) lazy var backgroundView:UIView = { + private(set) lazy var backgroundView:UIView? = { let _v = UIView() _v.backgroundColor = theme.color - _v.alpha = 0.0 + _v.alpha = 1.0 return _v }() private(set) lazy var navItem = UINavigationItem() - public static func create( + private let imageViewerPresentationDelegate = ImageViewerTransitionPresentationManager() + + public init( sourceView:UIImageView, imageDataSource: ImageDataSource?, options:[ImageViewerOption] = [], - initialIndex:Int = 0) -> ImageCarouselViewController { + initialIndex:Int = 0) { + self.initialSourceView = sourceView + self.initialIndex = initialIndex + self.options = options + self.imageDatasource = imageDataSource let pageOptions = [UIPageViewController.OptionsKey.interPageSpacing: 20] - - let imageCarousel = ImageCarouselViewController( + super.init( transitionStyle: .scroll, navigationOrientation: .horizontal, options: pageOptions) - imageCarousel.modalPresentationStyle = .overFullScreen - imageCarousel.modalPresentationCapturesStatusBarAppearance = true - - imageCarousel.sourceView = sourceView - imageCarousel.imageDatasource = imageDataSource - imageCarousel.options = options - imageCarousel.initialIndex = initialIndex - - return imageCarousel + transitioningDelegate = imageViewerPresentationDelegate + modalPresentationStyle = .custom + modalPresentationCapturesStatusBarAppearance = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } private func addNavBar() { @@ -80,6 +97,7 @@ public class ImageCarouselViewController:UIPageViewController { } private func addBackgroundView() { + guard let backgroundView = backgroundView else { return } view.addSubview(backgroundView) backgroundView.bindFrameToSuperview() view.sendSubviewToBack(backgroundView) @@ -118,36 +136,23 @@ public class ImageCarouselViewController:UIPageViewController { addNavBar() applyOptions() - view.backgroundColor = .clear dataSource = self - let initialVC = ImageViewerController(sourceView: sourceView) - initialVC.index = initialIndex if let imageDatasource = imageDatasource { - initialVC.imageItem = imageDatasource.imageItem(at: initialIndex) - } else { - // Use the image from source - initialVC.imageItem = .image(sourceView.image) - } - initialVC.animateOnDidAppear = true - initialVC.delegate = self - setViewControllers([initialVC], direction: .forward, animated: true, completion: nil) - } - - override public func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - UIView.animate(withDuration: 0.235) { - self.navBar.alpha = 1.0 + let initialVC:ImageViewerController = .init( + index: initialIndex, + imageItem: imageDatasource.imageItem(at: initialIndex)) + setViewControllers([initialVC], direction: .forward, animated: true) } } - + @objc private func dismiss(_ sender:UIBarButtonItem) { dismissMe(completion: nil) } public func dismissMe(completion: (() -> Void)? = nil) { - sourceView.alpha = 1.0 + sourceView?.alpha = 1.0 UIView.animate(withDuration: 0.235, animations: { self.view.alpha = 0.0 }) { _ in @@ -155,6 +160,10 @@ public class ImageCarouselViewController:UIPageViewController { } } + deinit { + initialSourceView?.alpha = 1.0 + } + @objc func diTapRightNavBarItem(_ sender:UIBarButtonItem) { guard let onTap = onRightNavBarTapped, @@ -181,12 +190,9 @@ extension ImageCarouselViewController:UIPageViewControllerDataSource { guard vc.index > 0 else { return nil } let newIndex = vc.index - 1 - let sourceView = newIndex == initialIndex ? self.sourceView : nil - return ImageViewerController.create( + return ImageViewerController.init( index: newIndex, - imageItem: imageDatasource.imageItem(at: newIndex), - sourceView: sourceView, - delegate: self) + imageItem: imageDatasource.imageItem(at: newIndex)) } public func pageViewController( @@ -198,17 +204,8 @@ extension ImageCarouselViewController:UIPageViewControllerDataSource { guard vc.index <= (imageDatasource.numberOfImages() - 2) else { return nil } let newIndex = vc.index + 1 - let sourceView = newIndex == initialIndex ? self.sourceView : nil - return ImageViewerController.create( + return ImageViewerController.init( index: newIndex, - imageItem: imageDatasource.imageItem(at: newIndex), - sourceView: sourceView, - delegate: self) - } -} - -extension ImageCarouselViewController:ImageViewerControllerDelegate { - func imageViewerDidClose(_ imageViewer: ImageViewerController) { - sourceView.alpha = 1.0 + imageItem: imageDatasource.imageItem(at: newIndex)) } } diff --git a/Sources/ImageViewerController.swift b/Sources/ImageViewerController.swift index d0bc079..94951b9 100644 --- a/Sources/ImageViewerController.swift +++ b/Sources/ImageViewerController.swift @@ -3,24 +3,20 @@ import UIKit import SDWebImage #endif -protocol ImageViewerControllerDelegate:class { - func imageViewerDidClose(_ imageViewer: ImageViewerController) -} - -class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { - - var index:Int = 0 - weak var delegate:ImageViewerControllerDelegate? - var imageItem:ImageItem! - var animateOnDidAppear:Bool = false - var sourceView:UIImageView? +class ImageViewerController:UIViewController, +UIGestureRecognizerDelegate { + var imageView: UIImageView = UIImageView(frame: .zero) + var backgroundView:UIView? { guard let _parent = parent as? ImageCarouselViewController else { return nil} return _parent.backgroundView } + var index:Int = 0 + var imageItem:ImageItem! + var navBar:UINavigationBar? { guard let _parent = parent as? ImageCarouselViewController else { return nil} @@ -33,19 +29,19 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { private var trailing:NSLayoutConstraint! private var bottom:NSLayoutConstraint! - private var imageView:UIImageView! private var scrollView:UIScrollView! - + private var lastLocation:CGPoint = .zero private var isAnimating:Bool = false private var maxZoomScale:CGFloat = 1.0 - init(sourceView:UIImageView? = nil) { + init( + index: Int, + imageItem:ImageItem) { + + self.index = index + self.imageItem = imageItem super.init(nibName: nil, bundle: nil) - self.sourceView = sourceView - - modalPresentationStyle = .overFullScreen - modalPresentationCapturesStatusBarAppearance = true } required init?(coder: NSCoder) { @@ -54,14 +50,14 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { override func loadView() { let view = UIView() - + view.backgroundColor = .clear self.view = view scrollView = UIScrollView() scrollView.delegate = self scrollView.showsVerticalScrollIndicator = false - + if #available(iOS 11.0, *) { scrollView.contentInsetAdjustmentBehavior = .never } else { @@ -70,8 +66,6 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { view.addSubview(scrollView) scrollView.bindFrameToSuperview() scrollView.backgroundColor = .clear - - imageView = UIImageView(frame: .zero) scrollView.addSubview(imageView) imageView.translatesAutoresizingMaskIntoConstraints = false @@ -84,28 +78,28 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { leading.isActive = true trailing.isActive = true bottom.isActive = true + } override func viewDidLoad() { super.viewDidLoad() + switch imageItem { case .image(let img): imageView.image = img imageView.layoutIfNeeded() - #if canImport(SDWebImage) + #if canImport(SDWebImage) case .url(let url, let placeholder): imageView.sd_setImage( with: url, - placeholderImage: placeholder ?? sourceView?.image, + placeholderImage: placeholder, options: [], - progress: nil) {[weak self] (img, err, type, url) in - DispatchQueue.main.async { - UIView.performWithoutAnimation { - self?.imageView.layoutIfNeeded() - } + progress: nil) {(img, err, type, url) in + DispatchQueue.main.async {[weak self] in + self?.layout() } - } - #endif + } + #endif default: break } @@ -115,16 +109,20 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - guard animateOnDidAppear == true else { - // skip animation - return - } - animateOnDidAppear = false - executeOpeningAnimation() + self.navBar?.alpha = 1.0 + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + self.navBar?.alpha = 0.0 } override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() + layout() + } + + private func layout() { updateConstraintsForSize(view.bounds.size) updateMinMaxZoomScaleForSize(view.bounds.size) } @@ -137,7 +135,7 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { panGesture.cancelsTouchesInView = false panGesture.delegate = self scrollView.addGestureRecognizer(panGesture) - + let pinchRecognizer = UITapGestureRecognizer( target: self, action: #selector(didPinch(_:))) pinchRecognizer.numberOfTapsRequired = 1 @@ -155,7 +153,7 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { doubleTapRecognizer.numberOfTapsRequired = 2 doubleTapRecognizer.numberOfTouchesRequired = 1 scrollView.addGestureRecognizer(doubleTapRecognizer) - + singleTapGesture.require(toFail: doubleTapRecognizer) } @@ -178,12 +176,12 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { x: lastLocation.x + translation.x, y: lastLocation.y + translation.y) } - + let diffY = view.center.y - container.center.y backgroundView?.alpha = 1.0 - abs(diffY/view.center.y) if gestureRecognizer.state == .ended { if abs(diffY) > 60 { - executeViewDismissalAnimation(diffY) + dismiss(animated: true) } else { executeCancelAnimation() } @@ -211,31 +209,36 @@ class ImageViewerController:UIViewController, UIGestureRecognizerDelegate { let pointInView = recognizer.location(in: imageView) zoomInOrOut(at: pointInView) } - + func gestureRecognizerShouldBegin( _ gestureRecognizer: UIGestureRecognizer) -> Bool { guard scrollView.zoomScale == scrollView.minimumZoomScale, - let panGesture = gestureRecognizer as? UIPanGestureRecognizer else { return false } - + let panGesture = gestureRecognizer as? UIPanGestureRecognizer + else { return false } + let velocity = panGesture.velocity(in: scrollView) return abs(velocity.y) > abs(velocity.x) } + + } // MARK: Adjusting the dimensions extension ImageViewerController { func updateMinMaxZoomScaleForSize(_ size: CGSize) { - if imageView.bounds.width == 0 || imageView.bounds.height == 0 { + + let targetSize = imageView.bounds.size + if targetSize.width == 0 || targetSize.height == 0 { return } let minScale = min( - size.width/imageView.bounds.width, - size.height/imageView.bounds.height) + size.width/targetSize.width, + size.height/targetSize.height) let maxScale = max( - (size.width + 1.0) / imageView.bounds.width, - (size.height + 1.0) / imageView.bounds.height) + (size.width + 1.0) / targetSize.width, + (size.height + 1.0) / targetSize.height) scrollView.minimumZoomScale = minScale scrollView.zoomScale = minScale @@ -257,6 +260,7 @@ extension ImageViewerController { } func updateConstraintsForSize(_ size: CGSize) { + let yOffset = max(0, (size.height - imageView.frame.height) / 2) top.constant = yOffset bottom.constant = yOffset @@ -266,44 +270,12 @@ extension ImageViewerController { trailing.constant = xOffset view.layoutIfNeeded() } - + } // MARK: Animation Related stuff extension ImageViewerController { - private func executeOpeningAnimation() { - - guard let _sourceView = sourceView else { return } - - let dummyImageView:UIImageView = UIImageView( - frame: _sourceView.frameRelativeToWindow()) - dummyImageView.clipsToBounds = true - dummyImageView.contentMode = .scaleAspectFill - dummyImageView.alpha = 1.0 - dummyImageView.image = imageView.image - view.addSubview(dummyImageView) - view.sendSubviewToBack(dummyImageView) - - _sourceView.alpha = 1.0 - imageView.alpha = 0.0 - backgroundView?.alpha = 0.0 - isAnimating = true - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {[weak self] in - guard let _self = self else { return } - UIView.animate(withDuration: 0.237, animations: { - dummyImageView.contentMode = .scaleAspectFit - dummyImageView.frame = _self.view.frame - _self.backgroundView?.alpha = 1.0 - _sourceView.alpha = 0.0 - }) { _ in - _self.imageView.alpha = 1.0 - dummyImageView.removeFromSuperview() - _self.isAnimating = false - } - } - } - private func executeCancelAnimation() { self.isAnimating = true UIView.animate( @@ -315,43 +287,6 @@ extension ImageViewerController { self?.isAnimating = false } } - - private func executeViewDismissalAnimation(_ diffY:CGFloat) { - isAnimating = true - - let dummyImageView:UIImageView = UIImageView(frame: imageView.frame) - dummyImageView.image = imageView.image - dummyImageView.clipsToBounds = false - dummyImageView.contentMode = .scaleAspectFill - view.addSubview(dummyImageView) - imageView.isHidden = true - - let exitFrame:CGRect = { () -> CGRect in - guard let _sourceFrame = self.sourceView?.frameRelativeToWindow() - else { - var imageViewFrame = self.imageView.frame - if diffY > 0 { - imageViewFrame.origin.y = -imageViewFrame.size.height - } else { - imageViewFrame.origin.y = view.frame.size.height - } - return imageViewFrame - } - return _sourceFrame - }() - - UIView.animate(withDuration: 0.237, animations: { - dummyImageView.frame = exitFrame - dummyImageView.clipsToBounds = true - self.backgroundView?.alpha = 0.0 - self.navBar?.alpha = 0.0 - }) { _ in - self.dismiss(animated: false) { - dummyImageView.removeFromSuperview() - self.delegate?.imageViewerDidClose(self) - } - } - } } extension ImageViewerController:UIScrollViewDelegate { @@ -365,21 +300,3 @@ extension ImageViewerController:UIScrollViewDelegate { } } - -// MARK: Shortcuts -extension ImageViewerController { - - static func create( - index: Int, - imageItem:ImageItem, - sourceView:UIImageView?, - delegate:ImageViewerControllerDelegate) -> ImageViewerController { - - let newVC = ImageViewerController() - newVC.index = index - newVC.imageItem = imageItem - newVC.sourceView = sourceView - newVC.delegate = delegate - return newVC - } -} diff --git a/Sources/UIImageView_Extensions.swift b/Sources/UIImageView_Extensions.swift index c19c62c..29f633d 100644 --- a/Sources/UIImageView_Extensions.swift +++ b/Sources/UIImageView_Extensions.swift @@ -19,7 +19,10 @@ extension UIImageView { public func setupImageViewer( options:[ImageViewerOption] = [], from:UIViewController? = nil) { - setup(datasource: nil, options: options, from: from) + setup( + datasource: SimpleImageDatasource(imageItems: [.image(image)]), + options: options, + from: from) } #if canImport(SDWebImage) @@ -127,13 +130,12 @@ extension UIImageView { @objc private func showImageViewer(_ sender:TapWithDataRecognizer) { guard let sourceView = sender.view as? UIImageView else { return } - - let imageCarousel = ImageCarouselViewController.create( + let imageCarousel = ImageCarouselViewController.init( sourceView: sourceView, imageDataSource: sender.imageDatasource, options: sender.options, initialIndex: sender.initialIndex) let presentFromVC = sender.from ?? vc - presentFromVC?.present(imageCarousel, animated: false, completion: nil) + presentFromVC?.present(imageCarousel, animated: true) } }