美文网首页
Swift4.0之自定义分段控制器(SegmentedContr

Swift4.0之自定义分段控制器(SegmentedContr

作者: Miu七七 | 来源:发表于2017-10-13 15:34 被阅读151次

    非常简单,就一个文件就解决了问题

    自定义分段控制器
    SwipeViewController.swift
    import UIKit
    /// 基于UIPageViewCotroller的切换视图
    class SwipeViewController: UIViewController {
        
        /// [对外接口]
        var titles = [String]()
        /// [对外接口]
        var viewControllers = [UIViewController]()
        
        private let barView: UIView = {
            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = .white
            return view
        }()
        
        private let contentView: UIView = {
            let view = UIView()
            view.translatesAutoresizingMaskIntoConstraints = false
            view.backgroundColor = .white
            return view
        }()
        
        private let barViewHeight: Int = 44
        
        private var pageController: UIPageViewController!
        fileprivate var indicatorView: UIView!
        private var pageScrollView: UIScrollView!
        
        fileprivate var currentIndex = 0
        
        fileprivate var isPageScrolling = false
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            view.addSubview(barView)
            view.addSubview(contentView)
            layoutContentView()
            
            setUpPageViewController()
            setupBarView()
        }
        
        func layoutContentView() {
            let views: [String: Any] = ["topLayoutGuide":topLayoutGuide,"barView":barView,"contentView":contentView,"bottomLayoutGuide":bottomLayoutGuide]
            let metrics: [String: NSNumber] = ["barViewHeight": NSNumber(value: Float(barViewHeight))]
            let horizonal1 = NSLayoutConstraint.constraints(withVisualFormat: "|[barView]|", options: .alignAllCenterY, metrics: nil, views: views)
            NSLayoutConstraint.activate(horizonal1)
            let horizonal2 = NSLayoutConstraint.constraints(withVisualFormat: "|[contentView]|", options: .alignAllCenterY, metrics: nil, views: views)
            NSLayoutConstraint.activate(horizonal2)
            let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[topLayoutGuide][barView(barViewHeight)]-(15)-[contentView][bottomLayoutGuide]", options: .alignAllCenterX, metrics: metrics, views: views)
            NSLayoutConstraint.activate(verticalConstraints)
        }
        
        func setupBarView() {
            guard titles.count > 0 else { return }
            let vcCount = viewControllers.count
            for index in 0..<vcCount {
                let button = UIButton(frame: CGRect(x: index*Int(view.bounds.width)/vcCount, y: 0, width: Int(view.bounds.width)/vcCount, height: barViewHeight))
                barView.addSubview(button)
                button.tag = index
                button.titleLabel?.font = UIFont.systemFont(ofSize: 14)
                button.backgroundColor = .white
                button.addTarget(self, action: #selector(tapNavigationButtonAction(_:)), for: .touchUpInside)
                button.setTitle(titles[index], for: .normal)
                button.setTitleColor(UIColor(hex: "666666"), for: .normal)
            }
            view.addSubview(barView)
            
            setUpIndicatorView()
        }
        //选中颜色
        func setUpIndicatorView() {
            indicatorView = UIView(frame: CGRect(x: 0, y: barViewHeight - 2, width: Int(view.bounds.width)/viewControllers.count, height: 2))
            indicatorView.backgroundColor = UIColor(hex: "AC7C1E")
            barView.addSubview(indicatorView)
        }
        
        func setUpPageViewController() {
            pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
            pageController.view.frame = contentView.bounds
            pageController.delegate = self
            pageController.dataSource = self
            pageController.setViewControllers([viewControllers[0]], direction: .forward, animated: true, completion: nil)
            addChildViewController(pageController)
            contentView.addSubview(pageController.view)
            pageController.didMove(toParentViewController: self)
            syncScrollView()
        }
        
        func syncScrollView() {
            for view in pageController.view.subviews {
                if view.isKind(of: UIScrollView.self) {
                    pageScrollView = view as? UIScrollView
                    pageScrollView.delegate = self
                }
            }
        }
        
        func tapNavigationButtonAction(_ sender: UIButton) {
            
            for subView in barView.subviews {
                if let btn = subView as? UIButton {
                    btn.setTitleColor(UIColor(hex: "666666"), for: .normal)
                }
            }
            sender.setTitleColor(UIColor(hex: "AC7C1E"), for: .normal)
            
            if !isPageScrolling {
                if sender.tag > currentIndex {
                    for index in currentIndex...sender.tag {
                        pageController.setViewControllers([viewControllers[index]], direction: .forward, animated: true, completion: { [weak self] complete in
                            if complete {
                                self?.currentIndex = index
                            }
                        })
                    }
                } else if sender.tag < currentIndex {
                    for index in (sender.tag...currentIndex).reversed() {
                        pageController.setViewControllers([viewControllers[index]], direction: .reverse, animated: true, completion: { [weak self] complete in
                            if complete {
                                self?.currentIndex = index
                            }
                        })
                    }
                }
            }
        }
    }
    
    extension SwipeViewController: UIPageViewControllerDataSource {
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
            let index = viewControllers.index(of: viewController)
            if var index = index {
                index += 1
                if index == viewControllers.count {
                    return nil
                }
                return viewControllers[index]
            } else {
                return nil
            }
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
            let index = viewControllers.index(of: viewController)
            if var index = index, index > 0{
                index -= 1
                return viewControllers[index]
            } else {
                return nil
            }
        }
    }
    
    extension SwipeViewController: UIPageViewControllerDelegate {
        
        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
            if completed {
                let last = pageViewController.viewControllers?.last
                if let lastVC = last {
                    currentIndex = viewControllers.index(of: lastVC)!
                }
            }
        }
    }
    
    extension SwipeViewController: UIScrollViewDelegate {
        
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let xFromCenter = view.bounds.width - scrollView.contentOffset.x
            let xCoor = Int(indicatorView.bounds.width) * currentIndex
            indicatorView.frame = CGRect(x: CGFloat(xCoor-Int(xFromCenter)/viewControllers.count), y: indicatorView.frame.origin.y, width: indicatorView.frame.size.width, height: indicatorView.frame.size.height)
            
        }
        func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
            isPageScrolling = true
        }
        
        func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
            isPageScrolling = false
        }
    }
    
    

    然后在其他控制器调用即可

    class MyCollectedViewController: SwipeViewController {
        override func viewDidLoad() {
          
            let articleVC: :UIViewController = UIViewController() 
            let videoVC: :UIViewController = UIViewController()
            viewControllers = [articleVC, videoVC]
            titles = ["资讯", "视频"]
            
            super.viewDidLoad()
           
        }
        
    

    相关文章

      网友评论

          本文标题:Swift4.0之自定义分段控制器(SegmentedContr

          本文链接:https://www.haomeiwen.com/subject/dfvzyxtx.html