From 5385fa32b4d11a5d95e9a5fb95d361f540dd8fbb Mon Sep 17 00:00:00 2001 From: Washaq Majeed Date: Wed, 29 Jul 2020 16:04:16 +0500 Subject: [PATCH 1/3] add caption support on both normal and fullscreen controller --- .../FullScreenSlideshowViewController.swift | 1 + .../Classes/Core/ImageSlideshow.swift | 9 ++- .../Classes/Core/ImageSlideshowItem.swift | 73 ++++++++++++++++--- ImageSlideshow/Classes/Core/InputSource.swift | 45 +++++++++--- 4 files changed, 104 insertions(+), 24 deletions(-) diff --git a/ImageSlideshow/Classes/Core/FullScreenSlideshowViewController.swift b/ImageSlideshow/Classes/Core/FullScreenSlideshowViewController.swift index a010d421..f4fb97a2 100644 --- a/ImageSlideshow/Classes/Core/FullScreenSlideshowViewController.swift +++ b/ImageSlideshow/Classes/Core/FullScreenSlideshowViewController.swift @@ -13,6 +13,7 @@ open class FullScreenSlideshowViewController: UIViewController { open var slideshow: ImageSlideshow = { let slideshow = ImageSlideshow() slideshow.zoomEnabled = true + slideshow.isFullScreenSlideShow = true slideshow.contentScaleMode = UIViewContentMode.scaleAspectFit slideshow.pageIndicatorPosition = PageIndicatorPosition(horizontal: .center, vertical: .bottom) // turns off the timer diff --git a/ImageSlideshow/Classes/Core/ImageSlideshow.swift b/ImageSlideshow/Classes/Core/ImageSlideshow.swift index 9d4fbd37..ed73cc8a 100644 --- a/ImageSlideshow/Classes/Core/ImageSlideshow.swift +++ b/ImageSlideshow/Classes/Core/ImageSlideshow.swift @@ -164,6 +164,13 @@ open class ImageSlideshow: UIView { } } } + + /// isFullScreenSlideShow handle fullscreen + open var isFullScreenSlideShow = false { + didSet { + reloadScrollView() + } + } /// Enables/disables user interactions open var draggingEnabled = true { @@ -320,7 +327,7 @@ open class ImageSlideshow: UIView { var i = 0 for image in scrollViewImages { - let item = ImageSlideshowItem(image: image, zoomEnabled: zoomEnabled, activityIndicator: activityIndicator?.create(), maximumScale: maximumScale) + let item = ImageSlideshowItem(image: image, zoomEnabled: zoomEnabled, activityIndicator: activityIndicator?.create(), maximumScale: maximumScale, isFullScreenSlideShow: isFullScreenSlideShow) item.imageView.contentMode = contentScaleMode slideshowItems.append(item) scrollView.addSubview(item) diff --git a/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift b/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift index 7b2136a8..cd083afe 100644 --- a/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift +++ b/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift @@ -14,6 +14,15 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { /// Image view to hold the image public let imageView = UIImageView() + /// Caption Label to show image caption + public let captionLabel = UILabel() + + /// Caption Container that add caption and background color + fileprivate var captionContainerView: UIView + + /// isFullScreenSlideShow ture if slider full screen controller shown + public let isFullScreenSlideShow: Bool + /// Activity indicator shown during image loading, when nil there won't be shown any public let activityIndicator: ActivityIndicatorView? @@ -53,12 +62,25 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { - parameter image: Input Source to load the image - parameter zoomEnabled: holds if it should be possible to zoom-in the image */ - init(image: InputSource, zoomEnabled: Bool, activityIndicator: ActivityIndicatorView? = nil, maximumScale: CGFloat = 2.0) { + init(image: InputSource, zoomEnabled: Bool, activityIndicator: ActivityIndicatorView? = nil, maximumScale: CGFloat = 2.0, isFullScreenSlideShow: Bool) { self.zoomEnabled = zoomEnabled self.image = image self.activityIndicator = activityIndicator self.maximumScale = maximumScale - + self.isFullScreenSlideShow = isFullScreenSlideShow + + let captionConstraintView = UIView() + captionConstraintView.addSubview(captionLabel) + if #available(iOS 9.0, *) { + let captionStackView = UIStackView() + captionStackView.axis = .vertical + captionStackView.alignment = .leading + captionStackView.addArrangedSubview(captionConstraintView) + captionContainerView = captionStackView + } else { + captionContainerView = captionConstraintView + } + super.init(frame: CGRect.null) imageViewWrapper.addSubview(imageView) @@ -69,7 +91,8 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { imageView.accessibilityIgnoresInvertColors = true } - imageViewWrapper.clipsToBounds = true + // clips to bounds false if fullscreen so we can show caption outside image + imageViewWrapper.clipsToBounds = !isFullScreenSlideShow imageViewWrapper.isUserInteractionEnabled = true if UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft { imageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi)) @@ -99,6 +122,22 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { singleTapGestureRecognizer!.numberOfTapsRequired = 1 singleTapGestureRecognizer!.isEnabled = false imageViewWrapper.addGestureRecognizer(singleTapGestureRecognizer!) + + captionContainerView.addSubview(captionConstraintView) + imageViewWrapper.addSubview(captionContainerView) + captionLabel.textColor = .white + captionLabel.numberOfLines = 0 + captionConstraintView.backgroundColor = UIColor.black.withAlphaComponent(0.5) + captionLabel.translatesAutoresizingMaskIntoConstraints = false + captionContainerView.translatesAutoresizingMaskIntoConstraints = false + + let leadingConstraint = NSLayoutConstraint(item: captionLabel, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: captionConstraintView, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 5) + let trailingConstraint = NSLayoutConstraint(item: captionLabel, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: captionConstraintView, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -5) + let topConstraint = NSLayoutConstraint(item: captionLabel, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: captionConstraintView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 5) + let bottomConstraint = NSLayoutConstraint(item: captionLabel, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: captionConstraintView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: -5) + + NSLayoutConstraint.activate([topConstraint, leadingConstraint, bottomConstraint, trailingConstraint,]) + } required public init?(coder aDecoder: NSCoder) { @@ -131,6 +170,10 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { contentSize = imageViewWrapper.frame.size maximumZoomScale = calculateMaximumScale() + + let leadingConstraint = NSLayoutConstraint(item: captionContainerView, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: imageViewWrapper, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 20) + let trailingConstraint = NSLayoutConstraint(item: captionContainerView, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: imageViewWrapper, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: -20) + NSLayoutConstraint.activate([leadingConstraint, trailingConstraint,]) } /// Request to load Image Source to Image View @@ -139,18 +182,24 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { isLoading = true imageReleased = false activityIndicator?.show() - image.load(to: self.imageView) {[weak self] image in + image.load(to: self.imageView) {[weak self] (image, caption, captionBottomConstraint, showCaptionOnlyInFullScreen) in + guard let self = self else { return } // set image to nil if there was a release request during the image load - if let imageRelease = self?.imageReleased, imageRelease { - self?.imageView.image = nil + if self.imageReleased { + self.imageView.image = nil } else { - self?.imageView.image = image + self.imageView.image = image } - self?.activityIndicator?.hide() - self?.loadFailed = image == nil - self?.isLoading = false - - self?.setNeedsLayout() + self.captionLabel.text = caption + self.captionContainerView.isHidden = (!self.isFullScreenSlideShow && showCaptionOnlyInFullScreen) || (caption ?? "").isEmpty + + NSLayoutConstraint(item: self.captionContainerView, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.imageViewWrapper, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: captionBottomConstraint).isActive = true + + self.activityIndicator?.hide() + self.loadFailed = image == nil + self.isLoading = false + + self.setNeedsLayout() } } } diff --git a/ImageSlideshow/Classes/Core/InputSource.swift b/ImageSlideshow/Classes/Core/InputSource.swift index 3689af2a..f787fee1 100644 --- a/ImageSlideshow/Classes/Core/InputSource.swift +++ b/ImageSlideshow/Classes/Core/InputSource.swift @@ -16,7 +16,7 @@ import UIKit - parameter callback: Callback called after image was set to the image view. - parameter image: Image that was set to the image view. */ - func load(to imageView: UIImageView, with callback: @escaping (_ image: UIImage?) -> Void) + func load(to imageView: UIImageView, with callback: @escaping (_ image: UIImage?, _ caption: String?, _ captionBottomConstraint: CGFloat, _ showCaptionOnlyInFullScreen: Bool) -> Void) /** Cancel image load on the image view @@ -29,28 +29,37 @@ import UIKit @objcMembers open class ImageSource: NSObject, InputSource { var image: UIImage + var caption: String + var captionBottomConstraint: CGFloat + var showCaptionOnlyInFullScreen: Bool /// Initializes a new Image Source with UIImage /// - parameter image: Image to be loaded - public init(image: UIImage) { + public init(image: UIImage, caption: String = "", captionBottomConstraint: CGFloat = 0, showCaptionOnlyInFullScreen: Bool = false) { self.image = image + self.caption = caption + self.captionBottomConstraint = captionBottomConstraint + self.showCaptionOnlyInFullScreen = showCaptionOnlyInFullScreen } /// Initializes a new Image Source with an image name from the main bundle /// - parameter imageString: name of the file in the application's main bundle @available(*, deprecated, message: "Use `BundleImageSource` instead") - public init?(imageString: String) { + public init?(imageString: String, caption: String = "", captionBottomConstraint: CGFloat = 0, showCaptionOnlyInFullScreen: Bool = false) { if let image = UIImage(named: imageString) { self.image = image + self.caption = caption + self.captionBottomConstraint = captionBottomConstraint + self.showCaptionOnlyInFullScreen = showCaptionOnlyInFullScreen super.init() } else { return nil } } - public func load(to imageView: UIImageView, with callback: @escaping (UIImage?) -> Void) { + public func load(to imageView: UIImageView, with callback: @escaping (UIImage?, String?, CGFloat, Bool) -> Void) { imageView.image = image - callback(image) + callback(image, caption, captionBottomConstraint, showCaptionOnlyInFullScreen) } } @@ -58,18 +67,25 @@ open class ImageSource: NSObject, InputSource { @objcMembers open class BundleImageSource: NSObject, InputSource { var imageString: String + var caption: String + var captionBottomConstraint: CGFloat + var showCaptionOnlyInFullScreen: Bool /// Initializes a new Image Source with an image name from the main bundle /// - parameter imageString: name of the file in the application's main bundle - public init(imageString: String) { + public init(imageString: String, caption: String = "", captionBottomConstraint: CGFloat = 0, showCaptionOnlyInFullScreen: Bool = false) { self.imageString = imageString + self.caption = caption + self.captionBottomConstraint = captionBottomConstraint + self.showCaptionOnlyInFullScreen = showCaptionOnlyInFullScreen + super.init() } - public func load(to imageView: UIImageView, with callback: @escaping (UIImage?) -> Void) { + public func load(to imageView: UIImageView, with callback: @escaping (UIImage?, String?, CGFloat, Bool) -> Void) { let image = UIImage(named: imageString) imageView.image = image - callback(image) + callback(image, caption, captionBottomConstraint, showCaptionOnlyInFullScreen) } } @@ -77,17 +93,24 @@ open class BundleImageSource: NSObject, InputSource { @objcMembers open class FileImageSource: NSObject, InputSource { var path: String + var caption: String + var captionBottomConstraint: CGFloat + var showCaptionOnlyInFullScreen: Bool /// Initializes a new Image Source with an image name from the main bundle /// - parameter imageString: name of the file in the application's main bundle - public init(path: String) { + public init(path: String, caption: String = "", captionBottomConstraint: CGFloat = 0, showCaptionOnlyInFullScreen: Bool = false) { self.path = path + self.caption = caption + self.captionBottomConstraint = captionBottomConstraint + self.showCaptionOnlyInFullScreen = showCaptionOnlyInFullScreen + super.init() } - public func load(to imageView: UIImageView, with callback: @escaping (UIImage?) -> Void) { + public func load(to imageView: UIImageView, with callback: @escaping (UIImage?, String?, CGFloat, Bool) -> Void) { let image = UIImage(contentsOfFile: path) imageView.image = image - callback(image) + callback(image, caption, captionBottomConstraint, showCaptionOnlyInFullScreen) } } From b7829c1691cc66bcdf39614251910da60627acf2 Mon Sep 17 00:00:00 2001 From: Washaq Majeed Date: Fri, 7 Aug 2020 15:37:18 +0500 Subject: [PATCH 2/3] add arrow on full screen --- .../ImageSlideshow.xcodeproj/project.pbxproj | 8 +++ ImageSlideshow/Assets/arrow-left-64x.png | Bin 0 -> 1727 bytes ImageSlideshow/Assets/arrow-right-64x.png | Bin 0 -> 1724 bytes .../FullScreenSlideshowViewController.swift | 64 ++++++++++++++++++ .../Classes/Core/ImageSlideshow.swift | 19 +++++- .../Classes/Core/ImageSlideshowItem.swift | 18 +++-- .../Core/ZoomAnimatedTransitioning.swift | 2 +- 7 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 ImageSlideshow/Assets/arrow-left-64x.png create mode 100644 ImageSlideshow/Assets/arrow-right-64x.png diff --git a/Example/ImageSlideshow.xcodeproj/project.pbxproj b/Example/ImageSlideshow.xcodeproj/project.pbxproj index b809b4a6..7b032ffe 100644 --- a/Example/ImageSlideshow.xcodeproj/project.pbxproj +++ b/Example/ImageSlideshow.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ D0E8A9F51D97EB94007EC517 /* UIImage+AspectFit.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E8A9EE1D97EB94007EC517 /* UIImage+AspectFit.swift */; }; D0E8A9F61D97EB94007EC517 /* UIImageView+Tools.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E8A9EF1D97EB94007EC517 /* UIImageView+Tools.swift */; }; D0E8A9F71D97EB94007EC517 /* ZoomAnimatedTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E8A9F01D97EB94007EC517 /* ZoomAnimatedTransitioning.swift */; }; + E6D20C7F24DD6427005CFB3C /* arrow-right-64x.png in Resources */ = {isa = PBXBuildFile; fileRef = E6D20C7D24DD6426005CFB3C /* arrow-right-64x.png */; }; + E6D20C8024DD6427005CFB3C /* arrow-left-64x.png in Resources */ = {isa = PBXBuildFile; fileRef = E6D20C7E24DD6426005CFB3C /* arrow-left-64x.png */; }; F539204C210F03610057EFB3 /* SwiftSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = F539204B210F03600057EFB3 /* SwiftSupport.swift */; }; F802998F20CE9EA7009D64DD /* PageIndicatorPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F802998E20CE9EA7009D64DD /* PageIndicatorPosition.swift */; }; F802999020CE9EA7009D64DD /* PageIndicatorPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = F802998E20CE9EA7009D64DD /* PageIndicatorPosition.swift */; }; @@ -74,6 +76,8 @@ D0E8A9EE1D97EB94007EC517 /* UIImage+AspectFit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIImage+AspectFit.swift"; path = "../../ImageSlideshow/Classes/Core/UIImage+AspectFit.swift"; sourceTree = ""; }; D0E8A9EF1D97EB94007EC517 /* UIImageView+Tools.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIImageView+Tools.swift"; path = "../../ImageSlideshow/Classes/Core/UIImageView+Tools.swift"; sourceTree = ""; }; D0E8A9F01D97EB94007EC517 /* ZoomAnimatedTransitioning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ZoomAnimatedTransitioning.swift; path = ../../ImageSlideshow/Classes/Core/ZoomAnimatedTransitioning.swift; sourceTree = ""; }; + E6D20C7D24DD6426005CFB3C /* arrow-right-64x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "arrow-right-64x.png"; path = "../../../ImageSlideshow/Assets/arrow-right-64x.png"; sourceTree = ""; }; + E6D20C7E24DD6426005CFB3C /* arrow-left-64x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "arrow-left-64x.png"; path = "../../../ImageSlideshow/Assets/arrow-left-64x.png"; sourceTree = ""; }; F539204B210F03600057EFB3 /* SwiftSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwiftSupport.swift; path = ../../ImageSlideshow/Classes/Core/SwiftSupport.swift; sourceTree = ""; }; F802998E20CE9EA7009D64DD /* PageIndicatorPosition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PageIndicatorPosition.swift; path = ../../ImageSlideshow/Classes/Core/PageIndicatorPosition.swift; sourceTree = ""; }; FD45C56C18E7B8EC08371B86 /* Pods-ImageSlideshow_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImageSlideshow_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ImageSlideshow_Example/Pods-ImageSlideshow_Example.debug.xcconfig"; sourceTree = ""; }; @@ -198,6 +202,8 @@ D00C7A2420B4C05C00E5725B /* Resources */ = { isa = PBXGroup; children = ( + E6D20C7E24DD6426005CFB3C /* arrow-left-64x.png */, + E6D20C7D24DD6426005CFB3C /* arrow-right-64x.png */, D00C7A2620B4C0A100E5725B /* ic_cross_white@2x.png */, D00C7A2520B4C0A000E5725B /* ic_cross_white@3x.png */, ); @@ -367,8 +373,10 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + E6D20C7F24DD6427005CFB3C /* arrow-right-64x.png in Resources */, D00C7A2720B4C0A100E5725B /* ic_cross_white@3x.png in Resources */, D00C7A2820B4C0A100E5725B /* ic_cross_white@2x.png in Resources */, + E6D20C8024DD6427005CFB3C /* arrow-left-64x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ImageSlideshow/Assets/arrow-left-64x.png b/ImageSlideshow/Assets/arrow-left-64x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec5eb9bb1f31e540f357d51356b8338f0715df6 GIT binary patch literal 1727 zcmY*aeOOXw6n{ZxM>&Ar&8%6>1-lg0d+npn`4&R9e$4bCxrg z^rg(TUibW^t}tMJK>*)G;>yXU$0ocEmH`Tfp$|GCF`9Hu>n zfB^v5v%(oWU{ANaXdC!jB}o~89YV2#xf#^-IFG>xo`}y9v)RBCj?n;#zyT`@1U8T( z0jPx-09V)pV5LXAsp^r7Rl45lO>6;1<|Wp^BvFz`zLL-04#monD8e||K@mljlxzV2 znhJu$B#}}`QY9ry6_6^Jynuk<*pjA_Ned9=hrwh%n@0+j$wj0J~g(@GZ;@wvy z|MDo7J}Jsbc+H2WneKjMXC^g zM#pfMZF;+WCF!9GVfD^mM{hB1Yc33&U?kXnU}!nUZJF8lVr|QdPTL1gI{JYo>p*=3 zR(1?SMn~G)vn7A$_pyV{^+!GK>6RL${(XIlo}SXla|&^JosXA-dKR&0+U71z$5`9! z?5tOPL&LebtV0kM-R)p!H>{fZBLSI_kr551R&Q-a&Uj2TkPA9bKi&KEUX0vUM;M)$ zSbAw}*4+A?Y9-JSdI zCr{Pg|IOAFcf8i_oNiY=SJyecTSW{NY7gjI?C(CQ&^bmo3A_;a>AU#p6faY;`Eap$ zW3<3yYf=nGFib_vRa(EGqGwOJn{E~Rpq`t}53{q|*0{KBuL;AxZOnUllW{-HJJ=dc z+gy^S%E6;sgu^i)t3cQuwzdci&spb<<7x4_4mmz=%cV&J>3RZ#fasiFXA&VteA_EV z`uqC@wABX$y~(>+pIL!&lAbrz4WU0^_O!32+of{JW_;s-rrGEcmm1wzbKZzs^=l&o$_B`-IaLPsh2qnigs94^R}%@& z&fO0-T-je=p;-aW&}Qg3M%2TuZ&JJ8>PVUIgff3DiTQ~b2GrYJ1fPE9B5=6rBPTLJ z0sYC6<+#z`3+6M*zKat-Hy$h_vVis-9Cl()#3N}AE3L3+O|JFTLnmY0$DDpO=e2fZ zR#a4Q2PdD-M|uXH-R@e~^h?^~lvT-#*8A9Q&KmPe`i&bN1aHglfEC7J)NB^${sHNj BwUht= literal 0 HcmV?d00001 diff --git a/ImageSlideshow/Assets/arrow-right-64x.png b/ImageSlideshow/Assets/arrow-right-64x.png new file mode 100644 index 0000000000000000000000000000000000000000..549d658937a1122934f4f631e5c0127c04fabb18 GIT binary patch literal 1724 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|0#YM9(|mmy zw18|51|~)!24;{FAY^FIWMBca85q=nGy?BF#CubedkjTuC zh>{3jAFJg2T)o7U{G?R9irfN_0tTB3D*7iAWdWaj57fXq!y$}cUk zRZ;?31P2gzmSmjSc~v(tC& z-hF-Pd_~K78jPJTk9<^wcCs@2N4WLn=j6o5OGx}s$lUTIB8g?o)~!#ECvCiLu5#lE_ z>14{*W&QeEhD?t>{!oeeyO+(?vZPVjQHNci!rlG&&I}W)uG2}|Vo$yK^{eXdg9i_` zbl(f!ID`E{RznqEc>b}ci`ZNxJ(Bz^*1mi^)9VWJl&c+IqhjtKUGH*I=2gDJYC-QO z-t2SJl>+$#!oGk1ZtrZD;Z*GilneSInVX;g{MEx~!$*uaPFRZX5qg+(Itf$ z85x%x(_>PO0F67txnr67i=spG?%cT}xZmdB3U&>p2_McW-)p~k?P*J8i;HqukMJuy z{VabD1p#dtk3)LA8!BJSn&2Fl@vCE1Pn*NCr9A9w{`0i&^x64#*3P6In>T-M^37ZG zawfY53qv`VOTp$X;XwDOo``zL*)LnNNa?(dL*(7tx2;=y1DJ1F`9JXc#22?-f7NfF ztMjTGn40DkT)JiUKG>+eO0xEr!!2j_xg96WnKJ&`Px`>DvSpUi!OsFG=9sCt$t}3@ z_`7Lv-flgob31yMe%a)!cj?Pi1|^3@)y8+ zZ&zrXw?LKgmr2+}?>+9Te#~NiqcA}@%i)OaiPLX(^?Y-evADkE^2>P1O}X)GhnS~) zJ;8a|M#u5@=1G=Urdrg9T6=SdFtT(IKu|JmTJ)13UZZz%>yw^VEPuIKHB`Z=;Uxb9_k^8dHbN=Q zDiuagt2rX>bItf!s_$ORa{fDqlx}1VZzIo#KWPub#00+o+4Akw+QWWN_O&u3&6|J9 z;`7Y|=ChgnAJu$hXmURz{HIRpVUU>NXI}>UcZJO$(1)kS(QZfZ67o-;gCW41lsDPzln?1}0RUNX*8Ik;}! zIuBl)mV ziBH8b|Ax6a2HUt2s;gP}pPZ2|tJAoTR2(gXsg_D>HZR^v@`+e(lmz+P#13x!moklKw1&I&zjWx4dOFAXzf$9QJS3j3^P6 Void)? = nil) -> FullScreenSlideshowViewController { + open func presentFullScreenController(from controller: UIViewController, contentScaleMode: UIViewContentMode = UIViewContentMode.scaleAspectFill, completion: (() -> Void)? = nil) -> FullScreenSlideshowViewController { let fullscreen = FullScreenSlideshowViewController() fullscreen.pageSelected = {[weak self] (page: Int) in self?.setCurrentPage(page, animated: false) } - + + fullscreen.slideshow.contentScaleMode = contentScaleMode fullscreen.initialPage = currentPage fullscreen.inputs = images slideshowTransitioningDelegate = ZoomAnimatedTransitioningDelegate(slideshowView: self, slideshowController: fullscreen) diff --git a/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift b/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift index cd083afe..916c103e 100644 --- a/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift +++ b/ImageSlideshow/Classes/Core/ImageSlideshowItem.swift @@ -40,6 +40,12 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { /// Maximum zoom scale open var maximumScale: CGFloat = 2.0 + + var hideCaption = false { + didSet { + updateCaption() + } + } fileprivate var lastFrame = CGRect.zero fileprivate var imageReleased = false @@ -91,8 +97,7 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { imageView.accessibilityIgnoresInvertColors = true } - // clips to bounds false if fullscreen so we can show caption outside image - imageViewWrapper.clipsToBounds = !isFullScreenSlideShow + imageViewWrapper.clipsToBounds = true imageViewWrapper.isUserInteractionEnabled = true if UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft { imageView.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi)) @@ -191,8 +196,8 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { self.imageView.image = image } self.captionLabel.text = caption - self.captionContainerView.isHidden = (!self.isFullScreenSlideShow && showCaptionOnlyInFullScreen) || (caption ?? "").isEmpty - + self.captionContainerView.isHidden = self.hideCaption || (!self.isFullScreenSlideShow && showCaptionOnlyInFullScreen) || (caption ?? "").isEmpty + NSLayoutConstraint(item: self.captionContainerView, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.imageViewWrapper, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: captionBottomConstraint).isActive = true self.activityIndicator?.hide() @@ -218,6 +223,11 @@ open class ImageSlideshowItem: UIScrollView, UIScrollViewDelegate { self.loadImage() } + + private func updateCaption() { + self.captionContainerView.isHidden = self.hideCaption || (captionLabel.text ?? "").isEmpty + } + // MARK: - Image zoom & size func isZoomed() -> Bool { diff --git a/ImageSlideshow/Classes/Core/ZoomAnimatedTransitioning.swift b/ImageSlideshow/Classes/Core/ZoomAnimatedTransitioning.swift index 9b29afae..f8277b07 100644 --- a/ImageSlideshow/Classes/Core/ZoomAnimatedTransitioning.swift +++ b/ImageSlideshow/Classes/Core/ZoomAnimatedTransitioning.swift @@ -224,7 +224,7 @@ class ZoomInAnimator: ZoomAnimator, UIViewControllerAnimatedTransitioning { referenceImageView.alpha = 0 - if let image = referenceImageView.image { + if let image = referenceImageView.image, referenceImageView.contentMode == .scaleAspectFit { transitionViewFinalFrame = image.tgr_aspectFitRectForSize(finalFrame.size) } } From 6ab8f04f0bf1a968eaa6fb7c391122fb98de235f Mon Sep 17 00:00:00 2001 From: Washaq Majeed Date: Thu, 15 Oct 2020 13:31:10 +0500 Subject: [PATCH 3/3] fix fullscreen presentation animation --- ImageSlideshow/Classes/Core/ImageSlideshow.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ImageSlideshow/Classes/Core/ImageSlideshow.swift b/ImageSlideshow/Classes/Core/ImageSlideshow.swift index 99ae442d..bb28805f 100644 --- a/ImageSlideshow/Classes/Core/ImageSlideshow.swift +++ b/ImageSlideshow/Classes/Core/ImageSlideshow.swift @@ -563,14 +563,18 @@ open class ImageSlideshow: UIView { fullscreen.pageSelected = {[weak self] (page: Int) in self?.setCurrentPage(page, animated: false) } - + let currentScaleMode = self.contentScaleMode + self.contentScaleMode = contentScaleMode fullscreen.slideshow.contentScaleMode = contentScaleMode fullscreen.initialPage = currentPage fullscreen.inputs = images slideshowTransitioningDelegate = ZoomAnimatedTransitioningDelegate(slideshowView: self, slideshowController: fullscreen) fullscreen.transitioningDelegate = slideshowTransitioningDelegate fullscreen.modalPresentationStyle = .custom - controller.present(fullscreen, animated: true, completion: completion) + controller.present(fullscreen, animated: true) { + self.contentScaleMode = currentScaleMode + completion?() + } return fullscreen }