{"id":30738929,"url":"https://github.com/moxcomic/rxsjpageviewcontroller","last_synced_at":"2025-09-03T22:43:02.330Z","repository":{"id":62453187,"uuid":"269042914","full_name":"moxcomic/RxSJPageViewController","owner":"moxcomic","description":"RxSJPageViewController","archived":false,"fork":false,"pushed_at":"2020-08-06T01:23:03.000Z","size":539,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-03T12:02:02.455Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moxcomic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-03T09:16:02.000Z","updated_at":"2023-07-03T18:42:52.000Z","dependencies_parsed_at":"2022-11-01T23:46:06.008Z","dependency_job_id":null,"html_url":"https://github.com/moxcomic/RxSJPageViewController","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/moxcomic/RxSJPageViewController","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxcomic%2FRxSJPageViewController","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxcomic%2FRxSJPageViewController/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxcomic%2FRxSJPageViewController/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxcomic%2FRxSJPageViewController/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moxcomic","download_url":"https://codeload.github.com/moxcomic/RxSJPageViewController/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moxcomic%2FRxSJPageViewController/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273523644,"owners_count":25120864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-03T22:42:59.117Z","updated_at":"2025-09-03T22:43:02.319Z","avatar_url":"https://github.com/moxcomic.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Before\n```\nclass ViewControllerUseDelegate: UIViewController, SJPageViewControllerDelegate, SJPageViewControllerDataSource, SJPageMenuBarDelegate {\n    fileprivate lazy var pageViewController = SJPageViewController()\n    \n    fileprivate lazy var pageMenuBar: SJPageMenuBar = {\n        $0.distribution = SJPageMenuBarDistributionFillEqually\n        $0.scrollIndicatorLayoutMode = SJPageMenuBarScrollIndicatorLayoutModeEqualItemViewContentWidth\n        return $0\n    }(SJPageMenuBar(frame: CGRect(x: 0, y: 300 - 44, width: UIScreen.main.bounds.width, height: 44)))\n    \n    fileprivate lazy var headerView: UIView = {\n        $0.backgroundColor = #colorLiteral(red: 0.2120229304, green: 0.6384014487, blue: 0.960485518, alpha: 1)\n        $0.addSubview(self.pageMenuBar)\n        return $0\n    }(UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300)))\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        pageViewController.view.frame = self.view.bounds\n        \n        pageViewController.delegate = self\n        pageViewController.dataSource = self\n        \n        self.addChild(pageViewController)\n        self.view.addSubview(pageViewController.view)\n    }\n    \n    func numberOfViewControllers(in pageViewController: SJPageViewController) -\u003e UInt {\n        return 3\n    }\n    \n    func pageViewController(_ pageViewController: SJPageViewController, viewControllerAt index: Int) -\u003e UIViewController {\n        switch index {\n        case 0: return UITableViewController()\n        case 1, 2: return UITableViewController()\n        default: return UITableViewController()\n        }\n    }\n    \n    func viewForHeader(in pageViewController: SJPageViewController) -\u003e UIView? {\n        return headerView\n    }\n    \n    func heightForHeaderPinToVisibleBounds(with pageViewController: SJPageViewController) -\u003e CGFloat {\n        return 300\n    }\n    \n    func modeForHeader(with pageViewController: SJPageViewController) -\u003e SJPageViewControllerHeaderMode {\n        return SJPageViewControllerHeaderModePinnedToTop\n    }\n    \n    func pageViewController(_ pageViewController: SJPageViewController, didScrollIn range: NSRange, distanceProgress progress: CGFloat) {\n        self.pageMenuBar.scroll(in: range, distanceProgress: progress)\n    }\n    \n    func pageMenuBar(_ bar: SJPageMenuBar, focusedIndexDidChange index: UInt) {\n        if !self.pageViewController.isViewControllerVisible(at: Int(index)) {\n            self.pageViewController.setViewControllerAt(Int(index))\n        }\n    }\n}\n```\n\n## After\n```\nclass ViewController: UIViewController {\n    fileprivate lazy var subject = BehaviorSubject(value: [SectionModel\u003cString, String\u003e]())\n    \n    fileprivate lazy var pageViewController = SJPageViewController()\n    \n    fileprivate lazy var pageMenuBar: SJPageMenuBar = {\n        $0.distribution = SJPageMenuBarDistributionFillEqually\n        $0.scrollIndicatorLayoutMode = SJPageMenuBarScrollIndicatorLayoutModeEqualItemViewContentWidth\n        return $0\n    }(SJPageMenuBar(frame: CGRect(x: 0, y: 300 - 44, width: UIScreen.main.bounds.width, height: 44)))\n    \n    // HeaderView一定要在外面定义，如果在configureHeaderView内定义则添加在HeaderView上的子控件将不会显示\n    fileprivate lazy var headerView: UIView = {\n        $0.backgroundColor = #colorLiteral(red: 0.2120229304, green: 0.6384014487, blue: 0.960485518, alpha: 1)\n        $0.addSubview(self.pageMenuBar)\n        return $0\n    }(UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 300)))\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        pageViewController.view.frame = self.view.bounds\n        \n        self.addChild(pageViewController)\n        self.view.addSubview(pageViewController.view)\n        \n        let dataSource = RxSJPageViewControllerReloadDataSource\u003cSectionModel\u003cString, String\u003e\u003e(configureViewController: {\n            (_, pageVC, index, element) in\n            switch element.identity {\n            case \"AAAA\": return UITableViewController()\n            case \"BBBB\", \"CCCC\": return UITableViewController()\n            default: return UITableViewController()\n            }\n        }, configureHeaderView: { [weak self] _, _ in\n            guard let self = self else { return nil }\n            return (self.headerView, 44 + 44, SJPageViewControllerHeaderModePinnedToTop)\n        })\n        self.subject.asObserver().bind(to: self.pageViewController.rx.pages(dataSource: dataSource)).disposed(by: rx.disposeBag)\n        self.pageMenuBar.itemViews = [\"AAAA\", \"BBBB\", \"CCCC\"].map { SJPageMenuItemView($0) }\n        \n        self.pageMenuBar.rx.focusedIndexDidChange.bind { [weak self] (pageMenuBar, index) in\n            guard let self = self else { return }\n            if !self.pageViewController.isViewControllerVisible(at: index) {\n                self.pageViewController.setViewControllerAt(index)\n            }\n        }.disposed(by: rx.disposeBag)\n        \n        subject.onNext([SectionModel\u003cString, String\u003e(model: \"\", items: [\"AAAA\", \"BBBB\", \"CCCC\"])])\n        \n        pageViewController.rx.didScrollIn.bind { [weak self] (pageViewController, range, progress) in\n            guard let self = self else { return }\n            self.pageMenuBar.scroll(in: range, distanceProgress: progress)\n        }.disposed(by: rx.disposeBag)\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoxcomic%2Frxsjpageviewcontroller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoxcomic%2Frxsjpageviewcontroller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoxcomic%2Frxsjpageviewcontroller/lists"}