123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- import UIKit
- public protocol FFPageViewDataSource {
- func pageView(pageView: FFPageView, cellForItemAt index: Int) -> FFPageContentViewCell
- }
- public protocol FFPageViewDelegate {
- func pageViewWithClickMenu(pageView: FFPageView)
- }
- @IBDesignable
- public class FFPageView: UIView {
- private var pageMenuView = FFPageMenuView()
- private var pageContentView = FFPageContentView()
- private var needlayout = true
- private var rootVC: UIViewController?
- private var ffConstraints = [NSLayoutConstraint]()
-
- public var dataSource: FFPageViewDataSource?
- public var delegate: FFPageViewDelegate?
- var isNavigationMenu = true {
- willSet {
- if newValue != isNavigationMenu {
- needlayout = true
- setNeedsLayout()
- }
- }
- }
- public var sliderView = UIView() {
- willSet {
- if sliderView != newValue {
- pageMenuView.sliderView = newValue
- }
- }
- }
- public var selectedColor = UIColor.blue {
- willSet {
- if selectedColor != newValue {
- pageMenuView.selectedColor = newValue
- }
- }
- }
- public var normalColor = UIColor.black {
- willSet {
- if normalColor != newValue {
- pageMenuView.normalColor = newValue
- }
- }
- }
- public var pageMenuContentMode = FFPageMenuContentMode.scaleAspectFill {
- willSet {
- pageMenuView.pageMenuContentMode = newValue
- }
- }
- public var font = UIFont.systemFont(ofSize: 17) {
- willSet {
- if font != newValue {
- pageMenuView.font = newValue
- }
- }
- }
- public var titles = [String]() {
- willSet {
- if titles != newValue {
- pageMenuView.titles = newValue
- pageContentView.needLayout = true
- pageMenuView.setNeedsLayout()
- pageContentView.setNeedsLayout()
- }
- }
- }
- public override func layoutSubviews() {
- super.layoutSubviews()
- if needlayout {
- initSubViews()
- }
- }
- func initSubViews() {
- needlayout = false
- pageContentView.removeFromSuperview()
- pageMenuView.removeFromSuperview()
- NSLayoutConstraint.deactivate(ffConstraints)
- ffConstraints.removeAll()
- pageMenuView.pageDelegate = self
- pageContentView.dataSource = self
- pageContentView.pageDelegate = self
- addSubview(pageContentView)
- pageContentView.translatesAutoresizingMaskIntoConstraints = false
- pageMenuView.translatesAutoresizingMaskIntoConstraints = false
- let contentTopConstraint: NSLayoutConstraint
- var responder = self.next
- while responder != nil {
- if let targetVC = responder as? UIViewController {
- rootVC = targetVC
- break
- }
- responder = responder?.next
- }
- if #available(iOS 11.0, *) {
- pageContentView.contentInsetAdjustmentBehavior = .never
- } else {
- rootVC?.automaticallyAdjustsScrollViewInsets = false
- }
- switch isNavigationMenu {
- case false:
- addSubview(pageMenuView)
- let menuConstraints = [NSLayoutConstraint(item: pageMenuView,
- attribute: .top,
- relatedBy: .equal,
- toItem: self,
- attribute: .top,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageMenuView,
- attribute: .leading,
- relatedBy: .equal,
- toItem: self,
- attribute: .leading,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageMenuView,
- attribute: .trailing,
- relatedBy: .equal,
- toItem: self,
- attribute: .trailing,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageMenuView,
- attribute: .height,
- relatedBy: .equal,
- toItem: nil,
- attribute: .height,
- multiplier: 1,
- constant: 44)]
- contentTopConstraint = NSLayoutConstraint(item: pageContentView,
- attribute: .top,
- relatedBy: .equal,
- toItem: pageMenuView,
- attribute: .bottom,
- multiplier: 1,
- constant: 0)
- ffConstraints += menuConstraints
- case true:
- var barContentView: UIView?
- if #available(iOS 11, *) {
- barContentView = rootVC?
- .navigationController?
- .navigationBar
- .subviews
- .filter { NSStringFromClass($0.classForCoder).contains("NavigationBarContentView") }
- .first
- } else {
- barContentView = rootVC?.navigationController?.navigationBar
- }
- contentTopConstraint = NSLayoutConstraint(item: pageContentView,
- attribute: .top,
- relatedBy: .equal,
- toItem: self,
- attribute: .top,
- multiplier: 1,
- constant: 0)
- let menuConstraints = [NSLayoutConstraint(item: pageMenuView,
- attribute: .top,
- relatedBy: .equal,
- toItem: barContentView,
- attribute: .top,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageMenuView,
- attribute: .bottom,
- relatedBy: .equal,
- toItem: barContentView,
- attribute: .bottom,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageMenuView,
- attribute: .centerX,
- relatedBy: .equal,
- toItem: barContentView,
- attribute: .centerX,
- multiplier: 1,
- constant: 0)]
- ffConstraints += menuConstraints
- NotificationCenter.default.addObserver(forName: NSNotification.Name.init("UINavigationController.willShow"), object: nil, queue: nil, using: { (notification) in
- if let userInfo = notification.userInfo,
- let vc = userInfo["targetController"] as? UIViewController,
- self.rootVC == vc {
- self.pageMenuView.isHidden = false
- } else {
- self.pageMenuView.isHidden = true
- }
- })
- }
- let contentConstraints = [contentTopConstraint,
- NSLayoutConstraint(item: pageContentView,
- attribute: .leading,
- relatedBy: .equal,
- toItem: self,
- attribute: .leading,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageContentView,
- attribute: .trailing,
- relatedBy: .equal,
- toItem: self,
- attribute: .trailing,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageContentView,
- attribute: .bottom,
- relatedBy: .equal,
- toItem: self,
- attribute: .bottom,
- multiplier: 1,
- constant: 0),
- NSLayoutConstraint(item: pageContentView,
- attribute: .width,
- relatedBy: .equal,
- toItem: self,
- attribute: .width,
- multiplier: 1,
- constant: 0)]
- ffConstraints += contentConstraints
- NSLayoutConstraint.activate(ffConstraints)
- }
- public func dequeue(with identifier: String) -> FFPageContentViewCell {
- return pageContentView.dequeue(with: identifier)
- }
- public func register(nib: UINib, with identifier: String) {
- pageContentView.register(nib: nib, with: identifier)
- }
- public func register(cell: AnyClass, with identifier: String) {
- pageContentView.register(cell: cell, with: identifier)
- }
- deinit {
- NotificationCenter.default.removeObserver(self)
- }
- }
- extension FFPageView: FFPageMenuViewDelegate {
- public func pageMenuView(pageMenuView: FFPageMenuView, didSelectItemAt index: Int) {
- pageContentView.scrollRectToVisible(CGRect(x: CGFloat(index) * frame.width, y: 0, width: frame.width, height: frame.height), animated: true)
- if let delegate = delegate {
- delegate.pageViewWithClickMenu(pageView: self)
- }
- }
- }
- extension FFPageView: FFPageContentViewDelegate {
- public func pageContentView(pageContentView: FFPageContentView, didSelectItemAt index: Int) {
- let offset = pageContentView.contentOffset.x / pageContentView.frame.width
- pageMenuView.scroll(offset: offset)
- }
- }
- extension FFPageView: FFPageContentViewDataSource {
- public func pageContentView(pageContentView: FFPageContentView, cellForItemAt index: Int) -> FFPageContentViewCell {
- guard let dataSource = dataSource else {
- fatalError("\(self) did not set up FFPageViewDataSource")
- }
- return dataSource.pageView(pageView: self, cellForItemAt: index)
- }
- public func numberOfSections(in pageContentView: FFPageContentView) -> Int {
- return titles.count
- }
- }
- extension UIViewController: UINavigationControllerDelegate {
- public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
- NotificationCenter.default.post(name: NSNotification.Name("UINavigationController.willShow"), object: nil, userInfo: ["targetController": viewController])
- }
- }
|