From 27d1d6dcc763306b1748e66318a3e40adfec71bf Mon Sep 17 00:00:00 2001 From: Heberti Almeida Date: Thu, 7 Jul 2016 01:01:37 -0300 Subject: [PATCH] Handle multiple scroll directions --- Example/Example/ViewController.swift | 1 + Source/FolioReaderCenter.swift | 71 ++++++++++++++++++---------- Source/FolioReaderConfig.swift | 21 ++++++++ Source/FolioReaderContainer.swift | 7 ++- Source/FolioReaderKit.swift | 44 ++++++++++++++++- Source/FolioReaderPage.swift | 32 ++++++++----- 6 files changed, 136 insertions(+), 40 deletions(-) diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index d61afeb52..babf98373 100755 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -32,6 +32,7 @@ class ViewController: UIViewController { func openEpub(sampleNum:Int) { let config = FolioReaderConfig() config.shouldHideNavigationOnTap = sampleNum == 1 ? true : false + config.scrollDirection = sampleNum == 1 ? .horizontal : .vertical // See more at FolioReaderConfig.swift // config.enableTTS = false diff --git a/Source/FolioReaderCenter.swift b/Source/FolioReaderCenter.swift index 6285e941d..0856bae42 100755 --- a/Source/FolioReaderCenter.swift +++ b/Source/FolioReaderCenter.swift @@ -93,7 +93,8 @@ class ScrollScrubber: NSObject, UIScrollViewDelegate { } func sliderChange(slider:UISlider) { - let offset = CGPointMake(height()*CGFloat(slider.value), 0) + let offset = isVerticalDirection(CGPointMake(0, height()*CGFloat(slider.value)), + CGPointMake(height()*CGFloat(slider.value), 0)) scrollView().setContentOffset(offset, animated: false) } @@ -157,11 +158,12 @@ class ScrollScrubber: NSObject, UIScrollViewDelegate { } if scrollStart == nil { - scrollStart = scrollView.contentOffset.x + scrollStart = scrollView.contentOffset.forDirection() } } func scrollViewDidScroll(scrollView: UIScrollView) { + guard readerConfig.scrollDirection == .vertical else { return } if visible && usingSlider == false { setSliderVal() @@ -172,7 +174,7 @@ class ScrollScrubber: NSObject, UIScrollViewDelegate { show() } else if delegate.currentPage != nil && scrollStart != nil { - scrollDelta = scrollView.contentOffset.x - scrollStart + scrollDelta = scrollView.contentOffset.forDirection() - scrollStart if scrollDeltaTimer == nil && scrollDelta > (pageHeight * 0.2 ) || (scrollDelta * -1) > (pageHeight * 0.2) { show() @@ -197,7 +199,7 @@ class ScrollScrubber: NSObject, UIScrollViewDelegate { scrollDeltaTimer = nil } - scrollStart = scrollView().contentOffset.x + scrollStart = scrollView().contentOffset.forDirection() scrollDelta = 0 } @@ -217,7 +219,7 @@ class ScrollScrubber: NSObject, UIScrollViewDelegate { } private func scrollTop() -> CGFloat { - return delegate.currentPage.webView.scrollView.contentOffset.x + return delegate.currentPage.webView.scrollView.contentOffset.forDirection() } } @@ -256,7 +258,7 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio layout.sectionInset = UIEdgeInsetsZero layout.minimumLineSpacing = 0 layout.minimumInteritemSpacing = 0 - layout.scrollDirection = UICollectionViewScrollDirection.Horizontal + layout.scrollDirection = .direction() let background = isNight(readerConfig.nightModeBackground, UIColor.whiteColor()) view.backgroundColor = background @@ -292,7 +294,7 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio let scrubberY: CGFloat = readerConfig.shouldHideNavigationOnTap == true ? 50 : 74 scrollScrubber = ScrollScrubber(frame: CGRect(x: pageWidth + 10, y: scrubberY, width: 40, height: pageHeight - 100)) scrollScrubber.delegate = self -// view.addSubview(scrollScrubber.slider) + view.addSubview(scrollScrubber.slider) // Loading indicator let style: UIActivityIndicatorViewStyle = isNight(.White, .Gray) @@ -321,11 +323,12 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio let navText = isNight(UIColor.whiteColor(), UIColor.blackColor()) let font = UIFont(name: "Avenir-Light", size: 17)! setTranslucentNavigation(color: navBackground, tintColor: tintColor, titleColor: navText, andFont: font) - if FolioReader.sharedInstance.nightMode { - UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true) - } else { - UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.Default, animated: true) - } + +// if FolioReader.sharedInstance.nightMode { +// UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true) +// } else { +// UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.Default, animated: true) +// } } func configureNavBarButtons() { @@ -550,8 +553,13 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio self.scrollScrubber.slider.frame = scrollScrubberFrame // Adjust collectionView - self.collectionView.contentSize = CGSizeMake(pageWidth, pageHeight * CGFloat(self.totalPages)) - self.collectionView.setContentOffset(self.frameForPage(currentPageNumber).origin, animated: false) + self.collectionView.contentSize = isVerticalDirection( + CGSizeMake(pageWidth, pageHeight * CGFloat(self.totalPages)), + CGSizeMake(pageHeight, pageWidth * CGFloat(self.totalPages)) + ) + + let origin = self.frameForPage(currentPageNumber).origin + self.collectionView.setContentOffset(origin, animated: false) self.collectionView.collectionViewLayout.invalidateLayout() }) } @@ -581,18 +589,18 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio if orientation.isPortrait { if screenBounds.size.width < screenBounds.size.height { pageWidth = screenBounds.size.width - pageHeight = screenBounds.size.height - 20 - pageIndicatorHeight + pageHeight = screenBounds.size.height } else { pageWidth = screenBounds.size.height - pageHeight = screenBounds.size.width - 20 - pageIndicatorHeight + pageHeight = screenBounds.size.width } } else { if screenBounds.size.width > screenBounds.size.height { pageWidth = screenBounds.size.width - pageHeight = screenBounds.size.height - 20 - pageIndicatorHeight + pageHeight = screenBounds.size.height } else { pageWidth = screenBounds.size.height - pageHeight = screenBounds.size.width - 20 - pageIndicatorHeight + pageHeight = screenBounds.size.width } } } @@ -645,8 +653,9 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio func pagesForCurrentPage(page: FolioReaderPage?) { if let page = page { - pageIndicatorView.totalPages = Int(ceil(page.webView.scrollView.contentSize.width/pageWidth)) - let webViewPage = pageForOffset(currentPage.webView.scrollView.contentOffset.x, pageHeight: pageWidth) + let pageSize = isVerticalDirection(pageHeight, pageWidth) + pageIndicatorView.totalPages = Int(ceil(page.webView.scrollView.contentSize.forDirection()/pageSize)) + let webViewPage = pageForOffset(currentPage.webView.scrollView.contentOffset.x, pageHeight: pageSize) pageIndicatorView.currentPage = webViewPage } } @@ -686,7 +695,10 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio } func frameForPage(page: Int) -> CGRect { - return CGRectMake(pageWidth * CGFloat(page-1), 0, pageWidth, pageHeight) + return isVerticalDirection( + CGRectMake(0, pageHeight * CGFloat(page-1), pageWidth, pageHeight), + CGRectMake(pageWidth * CGFloat(page-1), 0, pageWidth, pageHeight) + ) } func changePageWith(page page: Int, animated: Bool = false, completion: (() -> Void)? = nil) { @@ -755,7 +767,7 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio } UIView.animateWithDuration(animated ? 0.3 : 0, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in - self.collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Left, animated: false) + self.collectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: .direction(), animated: false) }) { (finished: Bool) -> Void in if (completion != nil) { completion!() } } @@ -986,7 +998,11 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio if let position = FolioReader.defaults.valueForKey(kBookId) as? NSDictionary { let pageNumber = position["pageNumber"]! as! Int - let pageOffset = position["pageOffset"]! as! CGFloat + var pageOffset: CGFloat = 0 + + if let offset = isVerticalDirection(position["pageOffsetY"], position["pageOffsetX"]) as? CGFloat { + pageOffset = offset + } if isFirstLoad { updateCurrentPage(page) @@ -1041,15 +1057,18 @@ class FolioReaderCenter: UIViewController, UICollectionViewDelegate, UICollectio // Update current reading page if scrollView is UICollectionView {} else { - if let page = currentPage where page.webView.scrollView.contentOffset.x+pageWidth <= page.webView.scrollView.contentSize.width { - let webViewPage = pageForOffset(page.webView.scrollView.contentOffset.x, pageHeight: pageWidth) + let pageSize = isVerticalDirection(pageHeight, pageWidth) + + if let page = currentPage + where page.webView.scrollView.contentOffset.forDirection()+pageSize <= page.webView.scrollView.contentSize.forDirection() { + let webViewPage = pageForOffset(page.webView.scrollView.contentOffset.forDirection(), pageHeight: pageSize) if pageIndicatorView.currentPage != webViewPage { pageIndicatorView.currentPage = webViewPage } } } - scrollDirection = scrollView.contentOffset.x < pointNow.x ? .Right : .Left + scrollDirection = scrollView.contentOffset.forDirection() < pointNow.forDirection() ? .negative() : .positive() } func scrollViewDidEndDecelerating(scrollView: UIScrollView) { diff --git a/Source/FolioReaderConfig.swift b/Source/FolioReaderConfig.swift index ba4880b96..06fa421b5 100755 --- a/Source/FolioReaderConfig.swift +++ b/Source/FolioReaderConfig.swift @@ -8,6 +8,26 @@ import UIKit +public enum FolioReaderScrollDirection: Int { + + // Using Swift 3.0 specification: lower camel-case on enum cases + + case vertical + case horizontal + + /** + Returns the `UICollectionViewFlowLayout` scroll direction. + */ + public func collectionViewScrollDirection() -> UICollectionViewScrollDirection { + switch self { + case vertical: + return .Vertical + case horizontal: + return .Horizontal + } + } +} + public class FolioReaderConfig: NSObject { // Reader Colors public var tintColor: UIColor! @@ -22,6 +42,7 @@ public class FolioReaderConfig: NSObject { public lazy var mediaOverlayColor: UIColor! = self.tintColor // Custom actions + public var scrollDirection: FolioReaderScrollDirection = .vertical public var shouldHideNavigationOnTap = true public var allowSharing = true public var enableTTS = true diff --git a/Source/FolioReaderContainer.swift b/Source/FolioReaderContainer.swift index 91e6ff0ec..45261c5a4 100755 --- a/Source/FolioReaderContainer.swift +++ b/Source/FolioReaderContainer.swift @@ -99,9 +99,10 @@ class FolioReaderContainer: UIViewController, FolioReaderSidePanelDelegate { // Add gestures let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(FolioReaderContainer.handleTapGesture(_:))) tapGestureRecognizer.numberOfTapsRequired = 1 -// let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(FolioReaderContainer.handlePanGesture(_:))) centerNavigationController.view.addGestureRecognizer(tapGestureRecognizer) -// centerNavigationController.view.addGestureRecognizer(panGestureRecognizer) + + let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(FolioReaderContainer.handlePanGesture(_:))) + centerNavigationController.view.addGestureRecognizer(panGestureRecognizer) // Read async book if (epubPath != nil) { @@ -255,6 +256,8 @@ class FolioReaderContainer: UIViewController, FolioReaderSidePanelDelegate { } func handlePanGesture(recognizer: UIPanGestureRecognizer) { + guard readerConfig.scrollDirection == .vertical else { return } + let gestureIsDraggingFromLeftToRight = (recognizer.velocityInView(view).x > 0) switch(recognizer.state) { diff --git a/Source/FolioReaderKit.swift b/Source/FolioReaderKit.swift index d08bb2602..d89323ece 100755 --- a/Source/FolioReaderKit.swift +++ b/Source/FolioReaderKit.swift @@ -152,7 +152,8 @@ public class FolioReader : NSObject { if let currentPage = FolioReader.sharedInstance.readerCenter.currentPage { let position = [ "pageNumber": currentPageNumber, - "pageOffset": currentPage.webView.scrollView.contentOffset.x + "pageOffsetX": currentPage.webView.scrollView.contentOffset.x, + "pageOffsetY": currentPage.webView.scrollView.contentOffset.y ] FolioReader.defaults.setObject(position, forKey: kBookId) @@ -167,6 +168,47 @@ func isNight (f: T, _ l: T) -> T { return FolioReader.sharedInstance.nightMode ? f : l } +// MARK: - Scroll Direction Functions + +func isVerticalDirection (f: T, _ l: T) -> T { + return readerConfig.scrollDirection == .vertical ? f : l +} + +extension UICollectionViewScrollDirection { + static func direction() -> UICollectionViewScrollDirection { + return isVerticalDirection(.Vertical, .Horizontal) + } +} + +extension UICollectionViewScrollPosition { + static func direction() -> UICollectionViewScrollPosition { + return isVerticalDirection(.Top, .Left) + } +} + +extension CGPoint { + func forDirection() -> CGFloat { + return isVerticalDirection(self.y, self.x) + } +} + +extension CGSize { + func forDirection() -> CGFloat { + return isVerticalDirection(self.height, self.width) + } +} + +extension ScrollDirection { + static func negative() -> ScrollDirection { + return isVerticalDirection(.Down, .Right) + } + + static func positive() -> ScrollDirection { + return isVerticalDirection(.Up, .Left) + } +} + + // MARK: - Extensions internal extension NSBundle { diff --git a/Source/FolioReaderPage.swift b/Source/FolioReaderPage.swift index c099845a0..5a2b7b144 100755 --- a/Source/FolioReaderPage.swift +++ b/Source/FolioReaderPage.swift @@ -38,15 +38,21 @@ class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRecogni webView.dataDetectorTypes = [.None, .Link] webView.scrollView.showsVerticalScrollIndicator = false webView.scrollView.showsHorizontalScrollIndicator = false - webView.scrollView.pagingEnabled = true - webView.scrollView.bounces = false webView.backgroundColor = UIColor.clearColor() - webView.paginationMode = UIWebPaginationMode.LeftToRight - webView.paginationBreakingMode = UIWebPaginationBreakingMode.Page + self.contentView.addSubview(webView) } webView.delegate = self + if readerConfig.scrollDirection == .horizontal { + webView.scrollView.pagingEnabled = true + webView.paginationMode = .LeftToRight + webView.paginationBreakingMode = .Page + webView.scrollView.bounces = false + } else { + webView.scrollView.bounces = true + } + if colorView == nil { colorView = UIView(); colorView.backgroundColor = UIColor(rgba: "#131313") @@ -59,12 +65,12 @@ class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRecogni webView.addGestureRecognizer(tapGestureRecognizer) // var swipeLeftGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(FolioReaderPage.handleSwipeGesture(_:))) -// swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Left +// swipeLeftGestureRecognizer.direction = .Left // swipeLeftGestureRecognizer.delegate = self // webView.addGestureRecognizer(swipeLeftGestureRecognizer) // // var swipeRightGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(FolioReaderPage.handleSwipeGesture(_:))) -// swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirection.Right +// swipeRightGestureRecognizer.direction = .Right // swipeRightGestureRecognizer.delegate = self // webView.addGestureRecognizer(swipeRightGestureRecognizer) } @@ -143,9 +149,13 @@ class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRecogni // webView.scrollView.contentSize = CGSizeMake(pageWidth, webView.scrollView.contentSize.height) - if scrollDirection == .Right && isScrolling { - let bottomOffset = CGPointMake(webView.scrollView.contentSize.width - webView.scrollView.bounds.width, 0) - if bottomOffset.x >= 0 { + if scrollDirection == .negative() && isScrolling { + let bottomOffset = isVerticalDirection( + CGPointMake(0, webView.scrollView.contentSize.height - webView.scrollView.bounds.height), + CGPointMake(webView.scrollView.contentSize.width - webView.scrollView.bounds.width, 0) + ) + + if bottomOffset.forDirection() >= 0 { dispatch_async(dispatch_get_main_queue(), { webView.scrollView.setContentOffset(bottomOffset, animated: false) }) @@ -334,7 +344,7 @@ class FolioReaderPage: UICollectionViewCell, UIWebViewDelegate, UIGestureRecogni // MARK: - Scroll positioning func scrollPageToOffset(offset: String, animating: Bool) { - let jsCommand = "window.scrollTo(\(offset),0);" + let jsCommand = isVerticalDirection("window.scrollTo(0,\(offset));", "window.scrollTo(\(offset),0);") if animating { UIView.animateWithDuration(0.35, animations: { self.webView.js(jsCommand) @@ -458,7 +468,7 @@ extension UIWebView { // menu on existing highlight if isShare { - if action == #selector(UIWebView.colors(_:)) || (action == #selector(UIWebView.share(_:)) && readerConfig.allowSharing == true) || action == #selector(UIWebView.remove(_:)) { + if action == #selector(UIWebView.colors(_:)) || (action == #selector(UIWebView.share(_:)) && readerConfig.allowSharing) || action == #selector(UIWebView.remove(_:)) { return true } return false