From df42777ce4059148ab4d945c2fbdffb035b7f9d8 Mon Sep 17 00:00:00 2001 From: Lingchen Date: Mon, 29 Jun 2020 09:45:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Aquaman-Demo/SupermanViewController.swift | 2 + Aquaman/Aquaman.xcodeproj/project.pbxproj | 4 + ...AquamanPageViewController+Additional.swift | 170 +++++++++++++++++ .../Aquaman/AquamanPageViewController.swift | 173 ++---------------- 4 files changed, 192 insertions(+), 157 deletions(-) create mode 100644 Aquaman/Aquaman/AquamanPageViewController+Additional.swift diff --git a/Aquaman-Demo/SupermanViewController.swift b/Aquaman-Demo/SupermanViewController.swift index cca0194..b4ba56d 100644 --- a/Aquaman-Demo/SupermanViewController.swift +++ b/Aquaman-Demo/SupermanViewController.swift @@ -52,6 +52,8 @@ extension SupermanViewController: UITableViewDelegate, UITableViewDataSource { cell.textLabel?.text = "Update head view height" } else if indexPath.row == 1 { cell.textLabel?.text = "Set select" + } else { + cell.textLabel?.text = "Title" } return cell } diff --git a/Aquaman/Aquaman.xcodeproj/project.pbxproj b/Aquaman/Aquaman.xcodeproj/project.pbxproj index f6f881a..59ba7b5 100644 --- a/Aquaman/Aquaman.xcodeproj/project.pbxproj +++ b/Aquaman/Aquaman.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ DF7F9F1021E37969000F4317 /* AquamanChildViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */; }; DF7F9F1121E37969000F4317 /* NSCache+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0A21E37968000F4317 /* NSCache+Additional.swift */; }; DF7F9F1221E37969000F4317 /* AquamanPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */; }; + DFFEA09D24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -34,6 +35,7 @@ DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanChildViewController.swift; sourceTree = ""; }; DF7F9F0A21E37968000F4317 /* NSCache+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCache+Additional.swift"; sourceTree = ""; }; DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AquamanPageViewController.swift; sourceTree = ""; }; + DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AquamanPageViewController+Additional.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -90,6 +92,7 @@ DF0DDABA21E35C440086663E /* Aquaman.h */, DF744C3B239F4F1F003A8EB4 /* AquamanProtocol.swift */, DF7F9F0B21E37968000F4317 /* AquamanPageViewController.swift */, + DFFEA09C24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift */, DF7F9F0921E37968000F4317 /* AquamanChildViewController.swift */, DF7F9F0821E37968000F4317 /* AquaMainScrollView.swift */, DF7F9F0721E37968000F4317 /* AquamanContainView.swift */, @@ -209,6 +212,7 @@ DF7F9F1121E37969000F4317 /* NSCache+Additional.swift in Sources */, DF7F9F0D21E37969000F4317 /* UIScrollView+Additional.swift in Sources */, DF7F9F0F21E37969000F4317 /* AquaMainScrollView.swift in Sources */, + DFFEA09D24A8A5BE0043D896 /* AquamanPageViewController+Additional.swift in Sources */, DF7F9F1221E37969000F4317 /* AquamanPageViewController.swift in Sources */, DF7F9F0E21E37969000F4317 /* AquamanContainView.swift in Sources */, DF7F9F0C21E37969000F4317 /* UIViewController+Additional.swift in Sources */, diff --git a/Aquaman/Aquaman/AquamanPageViewController+Additional.swift b/Aquaman/Aquaman/AquamanPageViewController+Additional.swift new file mode 100644 index 0000000..626cd1a --- /dev/null +++ b/Aquaman/Aquaman/AquamanPageViewController+Additional.swift @@ -0,0 +1,170 @@ +// +// AquamanPageViewController.swift +// Aquaman +// +// Created by bawn on 2018/12/7. +// Copyright © 2018 bawn. All rights reserved.( http://bawn.github.io ) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +extension AquamanPageViewController { + public func updateHeaderViewHeight(animated: Bool = false, + duration: TimeInterval = 0.25, + completion: ((Bool) -> Void)? = nil) { + + headerViewHeight = headerViewHeightFor(self) + sillValue = headerViewHeight - menuViewPinHeight + + mainScrollView.headerViewHeight = headerViewHeight + headerViewConstraint?.constant = headerViewHeight + + var manualHandel = false + if mainScrollView.contentOffset.y < sillValue { + currentChildScrollView?.contentOffset = currentChildScrollView?.am_originOffset ?? .zero + currentChildScrollView?.am_isCanScroll = false + mainScrollView.am_isCanScroll = true + manualHandel = true + } else if mainScrollView.contentOffset.y == sillValue { + mainScrollView.am_isCanScroll = false + manualHandel = true + } + let isAdsorption = (headerViewHeight <= 0.0) ? true : !mainScrollView.am_isCanScroll + if animated { + UIView.animate(withDuration: duration, animations: { + self.mainScrollView.layoutIfNeeded() + if manualHandel { + self.pageController(self, menuView: isAdsorption) + } + }) { (finish) in + completion?(finish) + } + } else { + self.pageController(self, menuView: isAdsorption) + completion?(true) + } + } + + public func setSelect(index: Int, animation: Bool) { + let offset = CGPoint(x: contentScrollView.bounds.width * CGFloat(index), + y: contentScrollView.contentOffset.y) + contentScrollView.setContentOffset(offset, animated: animation) + if animation == false { + contentScrollViewDidEndScroll(contentScrollView) + } + } + + public func reloadData() { + mainScrollView.isUserInteractionEnabled = false + clear() + obtainDataSource() + updateOriginContent() + setupDataSource() + view.layoutIfNeeded() + if originIndex > 0 { + setSelect(index: originIndex, animation: false) + } else { + showChildViewContoller(at: originIndex) + didDisplayViewController(at: originIndex) + } + mainScrollView.isUserInteractionEnabled = true + } +} + + +extension AquamanPageViewController: UIScrollViewDelegate { + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + + if scrollView == mainScrollView { + pageController(self, mainScrollViewDidScroll: scrollView) + let offsetY = scrollView.contentOffset.y + if offsetY >= sillValue { + scrollView.contentOffset = CGPoint(x: 0, y: sillValue) + currentChildScrollView?.am_isCanScroll = true + scrollView.am_isCanScroll = false + pageController(self, menuView: !scrollView.am_isCanScroll) + } else { + + if scrollView.am_isCanScroll == false { + pageController(self, menuView: true) + scrollView.contentOffset = CGPoint(x: 0, y: sillValue) + } else { + pageController(self, menuView: false) + } + } + } else { + pageController(self, contentScrollViewDidScroll: scrollView) + layoutChildViewControlls() + } + } + + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + if scrollView == contentScrollView { + mainScrollView.isScrollEnabled = false + } + } + + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if scrollView == contentScrollView { + mainScrollView.isScrollEnabled = true + if decelerate == false { + contentScrollViewDidEndScroll(contentScrollView) + } + } + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + if scrollView == contentScrollView { + contentScrollViewDidEndScroll(contentScrollView) + } + } + + + public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + if scrollView == contentScrollView { + contentScrollViewDidEndScroll(contentScrollView) + } + } + + public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { + guard scrollView == mainScrollView else { + return false + } + currentChildScrollView?.setContentOffset(currentChildScrollView?.am_originOffset ?? .zero, animated: true) + return true + } + +} + +extension AquamanPageViewController { + internal func childScrollViewDidScroll(_ scrollView: UIScrollView) { + if scrollView.am_isCanScroll == false { + scrollView.contentOffset = scrollView.am_originOffset ?? .zero + } + let offsetY = scrollView.contentOffset.y + if offsetY <= (scrollView.am_originOffset ?? .zero).y { + scrollView.contentOffset = scrollView.am_originOffset ?? .zero + scrollView.am_isCanScroll = false + mainScrollView.am_isCanScroll = true + } + } +} diff --git a/Aquaman/Aquaman/AquamanPageViewController.swift b/Aquaman/Aquaman/AquamanPageViewController.swift index 7d3c305..008542d 100644 --- a/Aquaman/Aquaman/AquamanPageViewController.swift +++ b/Aquaman/Aquaman/AquamanPageViewController.swift @@ -29,7 +29,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour public private(set) var currentViewController: (UIViewController & AquamanChildViewController)? public private(set) var currentIndex = 0 - private var originIndex = 0 + internal var originIndex = 0 lazy public private(set) var mainScrollView: AquaMainScrollView = { let scrollView = AquaMainScrollView() @@ -38,7 +38,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour return scrollView }() - lazy private var contentScrollView: UIScrollView = { + lazy internal var contentScrollView: UIScrollView = { let scrollView = UIScrollView() scrollView.delegate = self scrollView.bounces = false @@ -64,19 +64,19 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour private var contentScrollViewConstraint: NSLayoutConstraint? private var menuViewConstraint: NSLayoutConstraint? - private var headerViewConstraint: NSLayoutConstraint? + internal var headerViewConstraint: NSLayoutConstraint? private var mainScrollViewConstraints: [NSLayoutConstraint] = [] - private var headerViewHeight: CGFloat = 0.0 + internal var headerViewHeight: CGFloat = 0.0 private let headerContentView = UIView() private let menuContentView = UIView() private var menuViewHeight: CGFloat = 0.0 - private var menuViewPinHeight: CGFloat = 0.0 - private var sillValue: CGFloat = 0.0 + internal var menuViewPinHeight: CGFloat = 0.0 + internal var sillValue: CGFloat = 0.0 private var childControllerCount = 0 private var countArray = [Int]() private var containViews = [AquamanContainView]() - private var currentChildScrollView: UIScrollView? + internal var currentChildScrollView: UIScrollView? private var childScrollViewObservation: NSKeyValueObservation? private let memoryCache = NSCache() @@ -118,7 +118,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour childScrollViewObservation?.invalidate() } - private func didDisplayViewController(at index: Int) { + internal func didDisplayViewController(at index: Int) { guard childControllerCount > 0 , index >= 0 , index < childControllerCount @@ -145,7 +145,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour } - private func obtainDataSource() { + internal func obtainDataSource() { originIndex = originIndexFor(self) headerViewHeight = headerViewHeightFor(self) @@ -232,9 +232,10 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour ]) mainScrollView.bringSubviewToFront(menuContentView) + mainScrollView.bringSubviewToFront(headerContentView) } - private func updateOriginContent() { + internal func updateOriginContent() { mainScrollView.headerViewHeight = headerViewHeight mainScrollView.menuViewHeight = menuViewHeight @@ -250,7 +251,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour contentScrollViewConstraint?.constant = -menuViewHeight - menuViewPinHeight } - private func clear() { + internal func clear() { childScrollViewObservation?.invalidate() originIndex = 0 @@ -286,7 +287,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour memoryCache.removeAllObjects() } - private func setupDataSource() { + internal func setupDataSource() { memoryCache.countLimit = childControllerCount let headerView = headerViewFor(self) @@ -321,7 +322,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour } } - private func showChildViewContoller(at index: Int) { + internal func showChildViewContoller(at index: Int) { guard childControllerCount > 0 , index >= 0 , index < childControllerCount @@ -388,7 +389,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour } } - private func layoutChildViewControlls() { + internal func layoutChildViewControlls() { countArray.forEach { (index) in let containView = containViews[index] let isDisplayingInScreen = containView.displayingIn(view: view, containView: contentScrollView) @@ -396,7 +397,7 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour } } - private func contentScrollViewDidEndScroll(_ scrollView: UIScrollView) { + internal func contentScrollViewDidEndScroll(_ scrollView: UIScrollView) { let scrollViewWidth = scrollView.bounds.width guard scrollViewWidth > 0 else { return @@ -480,146 +481,4 @@ open class AquamanPageViewController: UIViewController, AMPageControllerDataSour } } -extension AquamanPageViewController { - public func updateHeaderViewHeight(animated: Bool = false, - duration: TimeInterval = 0.25, - completion: ((Bool) -> Void)? = nil) { - - headerViewHeight = headerViewHeightFor(self) - sillValue = headerViewHeight - menuViewPinHeight - - mainScrollView.headerViewHeight = headerViewHeight - headerViewConstraint?.constant = headerViewHeight - - var manualHandel = false - if mainScrollView.contentOffset.y < sillValue { - currentChildScrollView?.contentOffset = currentChildScrollView?.am_originOffset ?? .zero - currentChildScrollView?.am_isCanScroll = false - mainScrollView.am_isCanScroll = true - manualHandel = true - } else if mainScrollView.contentOffset.y == sillValue { - mainScrollView.am_isCanScroll = false - manualHandel = true - } - let isAdsorption = (headerViewHeight <= 0.0) ? true : !mainScrollView.am_isCanScroll - if animated { - UIView.animate(withDuration: duration, animations: { - self.mainScrollView.layoutIfNeeded() - if manualHandel { - self.pageController(self, menuView: isAdsorption) - } - }) { (finish) in - completion?(finish) - } - } else { - self.pageController(self, menuView: isAdsorption) - completion?(true) - } - } - - public func setSelect(index: Int, animation: Bool) { - let offset = CGPoint(x: contentScrollView.bounds.width * CGFloat(index), - y: contentScrollView.contentOffset.y) - contentScrollView.setContentOffset(offset, animated: animation) - if animation == false { - contentScrollViewDidEndScroll(contentScrollView) - } - } - - public func reloadData() { - mainScrollView.isUserInteractionEnabled = false - clear() - obtainDataSource() - updateOriginContent() - setupDataSource() - view.layoutIfNeeded() - if originIndex > 0 { - setSelect(index: originIndex, animation: false) - } else { - showChildViewContoller(at: originIndex) - didDisplayViewController(at: originIndex) - } - mainScrollView.isUserInteractionEnabled = true - } -} - -extension AquamanPageViewController: UIScrollViewDelegate { - - public func scrollViewDidScroll(_ scrollView: UIScrollView) { - - if scrollView == mainScrollView { - pageController(self, mainScrollViewDidScroll: scrollView) - let offsetY = scrollView.contentOffset.y - if offsetY >= sillValue { - scrollView.contentOffset = CGPoint(x: 0, y: sillValue) - currentChildScrollView?.am_isCanScroll = true - scrollView.am_isCanScroll = false - pageController(self, menuView: !scrollView.am_isCanScroll) - } else { - - if scrollView.am_isCanScroll == false { - pageController(self, menuView: true) - scrollView.contentOffset = CGPoint(x: 0, y: sillValue) - } else { - pageController(self, menuView: false) - } - } - } else { - pageController(self, contentScrollViewDidScroll: scrollView) - layoutChildViewControlls() - } - } - - public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { - if scrollView == contentScrollView { - mainScrollView.isScrollEnabled = false - } - } - - - public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { - if scrollView == contentScrollView { - mainScrollView.isScrollEnabled = true - if decelerate == false { - contentScrollViewDidEndScroll(contentScrollView) - } - } - } - - public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - if scrollView == contentScrollView { - contentScrollViewDidEndScroll(contentScrollView) - } - } - - - public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { - if scrollView == contentScrollView { - contentScrollViewDidEndScroll(contentScrollView) - } - } - - public func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { - guard scrollView == mainScrollView else { - return false - } - currentChildScrollView?.setContentOffset(currentChildScrollView?.am_originOffset ?? .zero, animated: true) - return true - } - -} - -extension AquamanPageViewController { - private func childScrollViewDidScroll(_ scrollView: UIScrollView) { - if scrollView.am_isCanScroll == false { - scrollView.contentOffset = scrollView.am_originOffset ?? .zero - } - let offsetY = scrollView.contentOffset.y - if offsetY <= (scrollView.am_originOffset ?? .zero).y { - scrollView.contentOffset = scrollView.am_originOffset ?? .zero - scrollView.am_isCanScroll = false - mainScrollView.am_isCanScroll = true - } - } -}