{"id":28520059,"url":"https://github.com/danie1s/dnspageview","last_synced_at":"2025-07-06T02:31:28.234Z","repository":{"id":56907704,"uuid":"123517498","full_name":"Danie1s/DNSPageView","owner":"Danie1s","description":"一个纯 Swift 的轻量级、灵活且易于使用的 pageView","archived":false,"fork":false,"pushed_at":"2023-06-02T10:12:53.000Z","size":1408,"stargazers_count":544,"open_issues_count":2,"forks_count":60,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-06-09T06:50:40.779Z","etag":null,"topics":["cocoapods","ios","pageview","swift","xcode"],"latest_commit_sha":null,"homepage":"","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/Danie1s.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-02T02:10:30.000Z","updated_at":"2025-03-17T05:17:30.000Z","dependencies_parsed_at":"2024-06-18T22:34:43.614Z","dependency_job_id":"b4286566-23b0-4e79-b655-a3c6f8633dc5","html_url":"https://github.com/Danie1s/DNSPageView","commit_stats":{"total_commits":72,"total_committers":4,"mean_commits":18.0,"dds":0.5138888888888888,"last_synced_commit":"d44bcaffc0f5a00d2ed2b64daa563759e31b7692"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/Danie1s/DNSPageView","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Danie1s%2FDNSPageView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Danie1s%2FDNSPageView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Danie1s%2FDNSPageView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Danie1s%2FDNSPageView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Danie1s","download_url":"https://codeload.github.com/Danie1s/DNSPageView/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Danie1s%2FDNSPageView/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263838636,"owners_count":23518124,"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","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":["cocoapods","ios","pageview","swift","xcode"],"created_at":"2025-06-09T06:38:07.398Z","updated_at":"2025-07-06T02:31:28.228Z","avatar_url":"https://github.com/Danie1s.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DNSPageView\n\n[![Version](https://img.shields.io/cocoapods/v/DNSPageView.svg?style=flat)](http://cocoapods.org/pods/DNSPageView)\n[![License](https://img.shields.io/cocoapods/l/DNSPageView.svg?style=flat)](http://cocoapods.org/pods/DNSPageView)\n[![Platform](https://img.shields.io/cocoapods/p/DNSPageView.svg?style=flat)](http://cocoapods.org/pods/DNSPageView)\n\n[English Introduction](https://github.com/Danie1s/DNSPageView/blob/master/README_EN.md)\n\nDNSPageView 一个纯 Swift 的轻量级、灵活且易于使用的 `PageView` 框架，`titleView` 和 `contentView` 可以布局在任意地方，可以纯代码初始化，也可以使用 `xib` 或者 `storyboard` 初始化，并且提供了常见样式属性进行设置。\n\n如果你使用的开发语言是 Objective-C，请使用 [DNSPageView-ObjC](https://github.com/Danie1s/DNSPageView-ObjC)\n\n- [Features](#features)\n- [Requirements](#requirements)\n- [Installation](#installation)\n- [Example](#example)\n- [Usage](#usage)\n  - [直接使用 PageView 初始化](#直接使用-pageview-初始化)\n  - [使用 xib 或者 storyboard 初始化](#使用-xib-或者-storyboard-初始化)\n  - [使用 PageViewManager 初始化](#使用-pageviewmanager-初始化)\n  - [样式 ](#样式)\n  - [事件回调](#事件回调)\n  - [常见问题](#常见问题)\n- [License](#license)\n\n## Features:\n\n- [x] 使用简单\n- [x] 多种初始化方式\n- [x] 灵活布局\n- [x] 常见的样式\n- [x] 双击 `titleView` 的回调\n- [x] `contentView` 滑动监听\n- [x] 适配 iOS 13 Dark Mode\n- [x] 动态改变样式\n- [x] 适配 RTL 布局\n\n## Requirements\n\n- iOS 9.0+\n- Xcode 10.2+\n- Swift 5.0+\n\n\n## Installation\n\n### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\n\u003e CocoaPods 1.1+ is required to build DNSPageView.\n\nTo integrate DNSPageView into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '9.0'\nuse_frameworks!\n\ntarget '\u003cYour Target Name\u003e' do\n    pod 'DNSPageView'\nend\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n\n### Manually\n\nIf you prefer not to use any of the aforementioned dependency managers, you can integrate DNSPageView into your project manually.\n\n\n\n## Example\n\nTo run the example project, clone the repo, and run `DNSPageView.xcodeproj` .\n\n\u003cimg src=\"https://github.com/Danie1s/DNSPageView/blob/master/Images/1.gif\" width=\"30%\" height=\"30%\"\u003e\n\n\u003cimg src=\"https://github.com/Danie1s/DNSPageView/blob/master/Images/2.gif\" width=\"30%\" height=\"30%\"\u003e\n\n\u003cimg src=\"https://github.com/Danie1s/DNSPageView/blob/master/Images/3.gif\" width=\"30%\" height=\"30%\"\u003e\n\n\u003cimg src=\"https://github.com/Danie1s/DNSPageView/blob/master/Images/4.gif\" width=\"30%\" height=\"30%\"\u003e\n\n\n\n\n\n## Usage\n\n### 直接使用 PageView 初始化\n\n```swift\n// 创建 PageStyle，设置样式\nlet style = PageStyle()\nstyle.isTitleViewScrollEnabled = true\nstyle.isTitleScaleEnabled = true\n\n// 设置标题内容\nlet titles = [\"头条\", \"视频\", \"娱乐\", \"要问\", \"体育\" , \"科技\" , \"汽车\" , \"时尚\" , \"图片\" , \"游戏\" , \"房产\"]\n\n// 创建每一页对应的 controller\nlet childViewControllers: [UIViewController] = titles.map { _ -\u003e UIViewController in\n    let controller = UIViewController()\n    addChild(controller)\n    return controller\n}\n\nlet y = UIApplication.shared.statusBarFrame.height + (navigationController?.navigationBar.frame.height ?? 0)\nlet size = UIScreen.main.bounds.size\n\n// 创建对应的 PageView，并设置它的 frame\n// titleView 和 contentView 会连在一起\nlet pageView = PageView(frame: CGRect(x: 0, y: y, width: size.width, height: size.height - y), style: style, titles: titles, childViewControllers: childViewControllers)\nview.addSubview(pageView)\n```\n\n\n\n### 使用 xib 或者 storyboard 初始化\n\n 在 `xib` 或者 `storyboard` 中拖出 2 个 `UIView`，让它们分别继承 `PageTitleView` 和 `PageContentView`，拖线到代码中\n\n```swift\n@IBOutlet weak var titleView: PageTitleView!\n\n@IBOutlet weak var contentView: PageContentView!\n```\n\n对 PageTitleView 和 PageContentView 进行设置\n\n```swift\n// 创建 PageStyle，设置样式\nlet style = PageStyle()\nstyle.titleViewBackgroundColor = UIColor.red\nstyle.isShowCoverView = true\n\n// 设置标题内容\nlet titles = [\"头条\", \"视频\", \"娱乐\", \"要问\", \"体育\"]\n\n// 设置默认的起始位置\nlet startIndex = 2\n\n\n// 创建每一页对应的 controller\nlet childViewControllers: [UIViewController] = titles.map { _ -\u003e UIViewController in\n    let controller = UIViewController()\n    addChild(controller)\n    return controller\n}\n\n// 创建 PageViewManager 来设置它们的样式和布局\nlet pageViewManager = PageViewManager(style: style,\n                                  titles: titles,\n                                  childViewControllers: children,\n                                  currentIndex: currentIndex,\n                                  titleView: titleView,\n                                  contentView: contentView)\n```\n\n\n\n### 使用 PageViewManager 初始化\n创建 PageViewManager\n\n```swift\nprivate lazy var pageViewManager: PageViewManager = {\n    // 创建 PageStyle，设置样式\n    let style = PageStyle()\n    style.isShowBottomLine = true\n    style.isTitleViewScrollEnabled = true\n    style.titleViewBackgroundColor = UIColor.clear\n\n    // 设置标题内容\n    let titles = [\"头条\", \"视频\", \"娱乐\", \"要问\", \"体育\"]\n\n    // 创建每一页对应的 controller\n    let childViewControllers: [UIViewController] = titles.map { _ -\u003e UIViewController in\n        let controller = UIViewController()\n        addChild(controller)\n        return controller\n    }\n\n    return PageViewManager(style: style, titles: titles, childViewControllers: childViewControllers)\n}()\n```\n\n布局 titleView 和 contentView\n\n```swift\n// 单独设置 titleView 的 frame\nnavigationItem.titleView = pageViewManager.titleView\npageViewManager.titleView.frame = CGRect(x: 0, y: 0, width: 180, height: 44)\n\n// 单独设置 contentView 的大小和位置，可以使用 autolayout 或者 frame\nlet contentView = pageViewManager.contentView\nview.addSubview(pageViewManager.contentView)\ncontentView.snp.makeConstraints { (maker) in\n    maker.edges.equalToSuperview()\n}\n```\n\n\n\n### 样式\n\n`PageStyle` 中提供了常见样式的属性，可以按照不同的需求进行设置，包括可以设置初始显示的页面\n\n\n\n### 事件回调\n\nDNSPageView 提供了常见事件监听回调，它属于 `PageTitleViewDelegate` 的中的可选属性\n\n```swift\n/// DNSPageView 的事件回调，如果有需要，请让对应的 childViewController 遵守这个协议\n@objc public protocol PageEventHandleable: class {\n    \n    /// 重复点击 pageTitleView 后调用\n    @objc optional func titleViewDidSelectSameTitle()\n    \n    /// pageContentView 的上一页消失的时候，上一页对应的 controller 调用\n    @objc optional func contentViewDidDisappear()\n    \n    /// pageContentView 滚动停止的时候，当前页对应的 controller 调用\n    @objc optional func contentViewDidEndScroll()\n\n}\n```\n\n\n\n### 常见问题\n\n- `style.isTitleViewScrollEnabled`\n\n  如果 `titles` 的数量比较少，建议设置 `style.isTitleViewScrollEnabled = false`，`titleView` 会固定，`style.titleMargin` 不起作用，每个 `title` 平分整个 `titleView` 的宽度，下划线的宽度等于`title` 的宽度。\n\n  如果标签比较多，建议设置 `style.isTitleViewScrollEnabled = true`，`titleView` 会滑动，下划线的宽度随着 `title` 文字的宽度变化而变化\n\n- 标签下划线的宽度跟随文字的宽度\n\n  设置 `style.isTitleViewScrollEnabled = true`，可以参考 `Demo` 中的第四种样式。\n\n- 由于 `DNSPageView` 是基于 `UIScrollView` 实现，那么就无法避免它的一些特性：\n\n  - 当控制器被 `UINavigationController` 管理，且 `navigationBar.isTranslucent = true` 的时候，当前控制器的 `view` 是从 `y = 0` 开始布局的，所以为了防止部分内容被 `navigationBar` 遮挡，系统默认会给 `UIScrollView` 添加 offset。如果想取消这个特性：\n    - iOS 11 以前，在控制器中设置 `automaticallyAdjustsScrollViewInsets = false `\n    - iOS 11 以后引入 `SafeArea` 概念，设置 `UIScrollView` 的属性 `contentInsetAdjustmentBehavior = .never`\n    - 其实这个效果还与 `UIViewController` 的其他属性有关系，但因为各种组合的情景过于复杂，所以不在此一一描述\n\n  - `PageContentView` 用 `UICollectionView` 实现，所以这个特性有机会造成 `UICollectionView` 的经典警告：\n\n    \u003e The behavior of the UICollectionViewFlowLayout is not defined because:\n    \u003e\n    \u003e the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values\n\n    从而引发一些 Bug\n\n  - 以上只是可能出现的 Bug 之一，由于 `Demo` 不能覆盖所有的场景，不同的布局需求可能会引起不同的 Bug，开发者需要明确了解自己的布局需求，注意细节，了解 iOS 布局特性，并且作出对应的调整，不能完全参照 `Demo`。\n\n\n## License\n\nDNSPageView is available under the MIT license. See the LICENSE file for more info.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanie1s%2Fdnspageview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanie1s%2Fdnspageview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanie1s%2Fdnspageview/lists"}