iOS 全網最好用的分頁控制器

NestedPageViewController

github地址

一個用于 iOS 的嵌套頁面視圖控制器,提供平滑的滾動協(xié)調體驗。

平臺 iOS | Swift 5.0 | iOS 13.0+ | MIT License | CocoaPods v1.0.0 | SPM Compatible


功能特點

  • 支持頭部視圖、標簽欄和多個子視圖控制器
  • 支持內容滾動位置記錄
  • 支持局部刷新和全局刷新
  • 支持子頁面預加載
  • 支持頭部視圖拖拽滾動并帶動整體
  • 支持自定義標簽欄
  • 支持旋轉
  • 更多功能請下載demo

功能演示

記錄滾動位置 局部刷新 全局刷新
記錄滾動位置
局部刷新
全局刷新
頭部始終固定不動 頭部縮放+隱藏導航欄 顯示系統(tǒng) tabBar
頭部始終固定不動
頭部縮放+隱藏導航欄
顯示系統(tǒng)tabBar
滾到頂部 自定義標簽欄1 自定義標簽欄2
滾到頂部
自定義標簽欄1
自定義標簽欄2

系統(tǒng)要求

  • iOS 13.0+
  • Swift 5.0+

安裝

Swift Package Manager


[https://github.com/SPStore/NestedPageViewController.git](https://github.com/SPStore/NestedPageViewController.git)

CocoaPods

pod 'NestedPageViewController'

運行:

pod install

注意:如果 CocoaPods 編譯報錯,請在主工程 Targets -> Build Settings -> User Script Sandboxing 改為 No


使用方法

方式一:添加子控制器方式

import UIKit
import NestedPageViewController

class YourViewController: UIViewController {
    private var nestedPageViewController = NestedPageViewController()
    private var coverView = YourHeaderView()
    private var customTabStrip = YourCustomTabStrip()
    private let childControllerTitles = ["標簽一", "標簽二", "標簽三", "標簽四"]

    override func viewDidLoad() {
        super.viewDidLoad()
        setupNestedPageViewController()
    }

    private func setupNestedPageViewController() {
        nestedPageViewController.dataSource = self
        nestedPageViewController.delegate = self
        addChild(nestedPageViewController)
        view.addSubview(nestedPageViewController.view)
        nestedPageViewController.didMove(toParent: self)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let safeAreaTop = view.safeAreaInsets.top
        nestedPageViewController.view.frame = CGRect(
            x: 0, y: safeAreaTop,
            width: view.bounds.width,
            height: view.bounds.height - safeAreaTop
        )
    }
}

extension YourViewController: NestedPageViewControllerDataSource {
    func numberOfViewControllers(in pageViewController: NestedPageViewController) -> Int {
        childControllerTitles.count
    }

    func pageViewController(_ pageViewController: NestedPageViewController, viewControllerAt index: Int) -> (UIViewController & NestedPageScrollable)? {
        switch index {
        case 0: return YourChildViewController1()
        case 1: return YourChildViewController2()
        case 2: return YourChildViewController3()
        case 3: return YourChildViewController4()
        default: return nil
        }
    }

    func coverView(in pageViewController: NestedPageViewController) -> UIView? { coverView }
    func heightForCoverView(in pageViewController: NestedPageViewController) -> CGFloat { 200 }
    func tabStrip(in pageViewController: NestedPageViewController) -> UIView? { customTabStrip }
    func heightForTabStrip(in pageViewController: NestedPageViewController) -> CGFloat { 50 }
    func titlesForTabStrip(in pageViewController: NestedPageViewController) -> [String]? { nil }
}

extension YourViewController: NestedPageViewControllerDelegate {
    func pageViewController(_ pageViewController: NestedPageViewController, didScrollToPageAt index: Int) {
        print("當前頁面索引: \(index)")
    }

    func pageViewController(_ pageViewController: NestedPageViewController, contentScrollViewDidScroll scrollView: UIScrollView, headerOffset: CGFloat, isSticked: Bool) {
        if isSticked { /* 頭部完全吸頂 */ }
        else { /* 頭部未吸頂 */ }
    }
}

方式二:繼承方式

import UIKit
import NestedPageViewController

class YourNestedPageViewController: NestedPageViewController {
    private var coverView = YourHeaderView()
    private var customTabStrip = YourCustomTabStrip()
    private let childControllerTitles = ["標簽一", "標簽二", "標簽三", "標簽四"]

    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self
        delegate = self
    }

    override func viewDidLayoutSubviews() {
        containerInsets = UIEdgeInsets(top: view.safeAreaInsets.top, left: 0, bottom: 0, right: 0)
        super.viewDidLayoutSubviews()
    }

    override func pageViewController(_ pageViewController: NestedPageViewController, didScrollToPageAt index: Int) {
        super.pageViewController(pageViewController, didScrollToPageAt: index)
        print("當前頁面索引: \(index)")
    }

    override func pageViewController(_ pageViewController: NestedPageViewController, contentScrollViewDidScroll scrollView: UIScrollView, headerOffset: CGFloat, isSticked: Bool) {
        super.pageViewController(pageViewController, contentScrollViewDidScroll: scrollView, headerOffset: headerOffset, isSticked: isSticked)
    }
}

extension YourNestedPageViewController: NestedPageViewControllerDataSource {
    func numberOfViewControllers(in pageViewController: NestedPageViewController) -> Int { childControllerTitles.count }
    func pageViewController(_ pageViewController: NestedPageViewController, viewControllerAt index: Int) -> (UIViewController & NestedPageScrollable)? {
        switch index {
        case 0: return YourChildViewController1()
        case 1: return YourChildViewController2()
        case 2: return YourChildViewController3()
        case 3: return YourChildViewController4()
        default: return nil
        }
    }
    func coverView(in pageViewController: NestedPageViewController) -> UIView? { coverView }
    func heightForCoverView(in pageViewController: NestedPageViewController) -> CGFloat { 200 }
    func tabStrip(in pageViewController: NestedPageViewController) -> UIView? { customTabStrip }
    func heightForTabStrip(in pageViewController: NestedPageViewController) -> CGFloat { 50 }
    func titlesForTabStrip(in pageViewController: NestedPageViewController) -> [String]? { nil }
}


Objective-C 使用方式

OC 工程需橋接,示例參考:Example/NestedPageExample/Examples-OC


性能報告

  • [內存占用]


    memory.png
  • [CPU 使用率]


    cpu.png

實現(xiàn)原理

實現(xiàn)原理文檔


項目起源

前身是 8 年前開發(fā)的 HVScrollView 項目,靈感來自騰訊 Bugly 發(fā)布的特斯拉組件文章。
時光荏苒,8年過去了,我積累了更多的開發(fā)經驗和技術沉淀,現(xiàn)在將這個想法重新實現(xiàn)并開源,希望能為iOS開發(fā)社區(qū)提供一個更加完善、易用的嵌套滾動解決方案。NestedPageViewController在保留原有思想精髓的基礎上,進一步優(yōu)化了性能和用戶體驗,為現(xiàn)代iOS應用提供了更加流暢的頁面嵌套滾動效果。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容