From f5826cbe8925ffff19cb23b6803caf48623e69e1 Mon Sep 17 00:00:00 2001 From: Eleyan saad <38811888+eleyanSaad@users.noreply.github.com> Date: Thu, 9 Sep 2021 12:56:13 +0300 Subject: [PATCH 1/2] add intervael --- MediaSlideshow/Source/MediaSlideshow.swift | 72 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/MediaSlideshow/Source/MediaSlideshow.swift b/MediaSlideshow/Source/MediaSlideshow.swift index a8c89a0e..f8eef5bf 100644 --- a/MediaSlideshow/Source/MediaSlideshow.swift +++ b/MediaSlideshow/Source/MediaSlideshow.swift @@ -28,7 +28,7 @@ public protocol MediaSlideshowDelegate: class { @objc optional func mediaSlideshowDidEndDecelerating(_ mediaSlideshow: MediaSlideshow) } -/** +/** Used to represent position of the Page Control - hidden: Page Control is hidden - insideScrollView: Page Control is inside image slideshow @@ -73,6 +73,14 @@ open class MediaSlideshow: UIView { reloadScrollView() } } + + open var circular = true { + didSet { + if sources.count > 0 { + setMediaSources(sources) + } + } + } open var pageIndicator: PageIndicatorView? { didSet { @@ -177,6 +185,14 @@ open class MediaSlideshow: UIView { } } + /// Image change interval, zero stops the auto-scrolling + open var slideshowInterval = 0.0 { + didSet { + slideshowTimer?.invalidate() + slideshowTimer = nil + setTimerIfNeeded() + } + } /// Image preload configuration, can be sed to .fixed to enable lazy load or .all open var preload = ImagePreload.all @@ -189,6 +205,8 @@ open class MediaSlideshow: UIView { } } + fileprivate var slideshowTimer: Timer? + fileprivate var scrollViewImages = [MediaSource]() fileprivate var isAnimating: Bool = false /// Transitioning delegate to manage the transition to full screen controller @@ -242,6 +260,7 @@ open class MediaSlideshow: UIView { pageIndicator = UIPageControl() } + setTimerIfNeeded() layoutScrollView() } @@ -335,6 +354,8 @@ open class MediaSlideshow: UIView { reloadScrollView() layoutScrollView() layoutPageControl() + setTimerIfNeeded() + } // MARK: paging methods @@ -362,6 +383,24 @@ open class MediaSlideshow: UIView { } } } + + fileprivate func setTimerIfNeeded() { + if slideshowInterval > 0 && scrollViewImages.count > 1 && slideshowTimer == nil { + slideshowTimer = Timer.scheduledTimer(timeInterval: slideshowInterval, target: self, selector: #selector(MediaSlideshow.slideshowTick(_:)), userInfo: nil, repeats: true) + } + } + + func slideshowTick(_ timer: Timer) { + let page = scrollView.frame.size.width > 0 ? Int(scrollView.contentOffset.x / scrollView.frame.size.width) : 0 + var nextPage = page + 1 + + if !circular && page == scrollViewImages.count - 1 { + nextPage = 0 + } + + setScrollViewPage(nextPage, animated: true) + } + fileprivate func setCurrentPageForScrollViewPage(_ page: Int) { if scrollViewPage != page { @@ -383,6 +422,37 @@ open class MediaSlideshow: UIView { fileprivate func currentPageForScrollViewPage(_ page: Int) -> Int { page } + + fileprivate func restartTimer() { + if slideshowTimer?.isValid != nil { + slideshowTimer?.invalidate() + slideshowTimer = nil + } + + setTimerIfNeeded() + } + + + /// Stops slideshow timer + open func pauseTimer() { + slideshowTimer?.invalidate() + slideshowTimer = nil + } + + /// Restarts slideshow timer + open func unpauseTimer() { + setTimerIfNeeded() + } + + @available(*, deprecated, message: "use pauseTimer instead") + open func pauseTimerIfNeeded() { + pauseTimer() + } + + @available(*, deprecated, message: "use unpauseTimer instead") + open func unpauseTimerIfNeeded() { + unpauseTimer() + } /** Change the page to the next one From b1402cb69a917fdfaf7e6886dbedde95c3a9eaf6 Mon Sep 17 00:00:00 2001 From: Eleyan saad <38811888+eleyanSaad@users.noreply.github.com> Date: Thu, 9 Sep 2021 17:05:45 +0300 Subject: [PATCH 2/2] fix issue --- MediaSlideshow/Source/MediaSlideshow.swift | 82 ++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-) diff --git a/MediaSlideshow/Source/MediaSlideshow.swift b/MediaSlideshow/Source/MediaSlideshow.swift index f8eef5bf..2fbd2872 100644 --- a/MediaSlideshow/Source/MediaSlideshow.swift +++ b/MediaSlideshow/Source/MediaSlideshow.swift @@ -264,6 +264,11 @@ open class MediaSlideshow: UIView { layoutScrollView() } + open override func removeFromSuperview() { + super.removeFromSuperview() + pauseTimer() + } + open override func layoutSubviews() { super.layoutSubviews() @@ -350,7 +355,27 @@ open class MediaSlideshow: UIView { */ public func setMediaSources(_ sources: [MediaSource]) { self.sources = sources + pageIndicator?.numberOfPages = sources.count + + // in circular mode we add dummy first and last image to enable smooth scrolling + if circular && sources.count > 1 { + var scImages = [MediaSource]() + + if let last = sources.last { + scImages.append(last) + } + scImages += sources + if let first = sources.first { + scImages.append(first) + } + + scrollViewImages = scImages + } else { + scrollViewImages = sources + } + + reloadScrollView() layoutScrollView() layoutPageControl() @@ -366,7 +391,13 @@ open class MediaSlideshow: UIView { - parameter animated: true if animate the change */ open func setCurrentPage(_ newPage: Int, animated: Bool) { - setScrollViewPage(newPage, animated: animated) + var pageOffset = newPage + if circular && (scrollViewImages.count > 1) { + pageOffset += 1 + } + + setScrollViewPage(pageOffset, animated: animated) + } /** @@ -420,7 +451,19 @@ open class MediaSlideshow: UIView { } fileprivate func currentPageForScrollViewPage(_ page: Int) -> Int { - page + if circular { + if page == 0 { + // first page contains the last image + return Int(sources.count) - 1 + } else if page == scrollViewImages.count - 1 { + // last page contains the first image + return 0 + } else { + return page - 1 + } + } else { + return page + } } fileprivate func restartTimer() { @@ -459,10 +502,15 @@ open class MediaSlideshow: UIView { - Parameter animated: true if animate the change */ open func nextPage(animated: Bool) { + if !circular && currentPage == sources.count - 1 { + return + } if isAnimating { return } + setCurrentPage(currentPage + 1, animated: animated) + restartTimer() } /** @@ -470,13 +518,19 @@ open class MediaSlideshow: UIView { - Parameter animated: true if animate the change */ open func previousPage(animated: Bool) { + if !circular && currentPage == 0 { + return + } if isAnimating { return } - let newPage = scrollViewPage > 0 ? scrollViewPage - 1 : sources.count - 3 + + let newPage = scrollViewPage > 0 ? scrollViewPage - 1 : scrollViewImages.count - 3 setScrollViewPage(newPage, animated: animated) + restartTimer() } + @objc private func pageControlValueChanged() { if let currentPage = pageIndicator?.page { setCurrentPage(currentPage, animated: true) @@ -487,6 +541,7 @@ open class MediaSlideshow: UIView { extension MediaSlideshow: UIScrollViewDelegate { open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + restartTimer() willBeginDragging?() delegate?.mediaSlideshowWillBeginDragging?(self) } @@ -496,15 +551,32 @@ extension MediaSlideshow: UIScrollViewDelegate { didEndDecelerating?() delegate?.mediaSlideshowDidEndDecelerating?(self) } - +// +// open func scrollViewDidScroll(_ scrollView: UIScrollView) { +// // Updates the page indicator as the user scrolls (#204). Not called when not dragging to prevent flickers +// // when interacting with PageControl directly (#376). +// if scrollView.isDragging { +// pageIndicator?.page = currentPageForScrollViewPage(primaryVisiblePage) +// } +// } open func scrollViewDidScroll(_ scrollView: UIScrollView) { + if circular && (scrollViewImages.count > 1) { + let regularContentOffset = scrollView.frame.size.width * CGFloat(sources.count) + + if scrollView.contentOffset.x >= scrollView.frame.size.width * CGFloat(sources.count + 1) { + scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x - regularContentOffset, y: 0) + } else if scrollView.contentOffset.x <= 0 { + scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x + regularContentOffset, y: 0) + } + } + // Updates the page indicator as the user scrolls (#204). Not called when not dragging to prevent flickers // when interacting with PageControl directly (#376). if scrollView.isDragging { pageIndicator?.page = currentPageForScrollViewPage(primaryVisiblePage) } } - + public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { isAnimating = false }