{"id":13778675,"url":"https://github.com/fredyshox/PageView","last_synced_at":"2025-05-11T12:31:27.937Z","repository":{"id":37676034,"uuid":"239224766","full_name":"fredyshox/PageView","owner":"fredyshox","description":"SwiftUI view enabling navigation between pages of content, imitating the behaviour of UIPageViewController for iOS and watchOS","archived":false,"fork":false,"pushed_at":"2023-03-11T22:57:52.000Z","size":2756,"stargazers_count":582,"open_issues_count":10,"forks_count":39,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-08-03T18:13:13.159Z","etag":null,"topics":["ios","pageview","swift","swiftui","uipagecontrol","uipageviewcontroller","watchos"],"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/fredyshox.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}},"created_at":"2020-02-09T00:31:06.000Z","updated_at":"2024-07-27T06:04:09.000Z","dependencies_parsed_at":"2024-01-17T01:07:38.737Z","dependency_job_id":null,"html_url":"https://github.com/fredyshox/PageView","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredyshox%2FPageView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredyshox%2FPageView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredyshox%2FPageView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fredyshox%2FPageView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fredyshox","download_url":"https://codeload.github.com/fredyshox/PageView/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225048980,"owners_count":17412904,"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":["ios","pageview","swift","swiftui","uipagecontrol","uipageviewcontroller","watchos"],"created_at":"2024-08-03T18:00:56.080Z","updated_at":"2024-11-17T14:30:47.593Z","avatar_url":"https://github.com/fredyshox.png","language":"Swift","funding_links":[],"categories":["Pages","Swift","UI"],"sub_categories":["Content","Page"],"readme":"# PageView\n\nSwiftUI view enabling page-based navigation, imitating the behaviour of `UIPageViewController` in iOS.\n\n![watchOS screenshow](./Images/PageViews_watchOS.png)\n\n## Why\n\nSwiftUI doesn't have any kind of paging control component,  with features similar to `UIPageViewController` from UIKit. While on iOS this could be solved by wrapping `UIPageViewController` into  `UIViewRepresentable`, on watchOS horizontal/vertical paging functionality cannot be achieved without using storyboards, which forces developers into using multiple WKHostingControllers.\n\nThis package attempts to provide native SwiftUI component for navigation between pages of content.\n\n## Installation\n\nPackage requires iOS 14, watchOS 7 and Xcode 12.\n\n### Swift Package Manager\n\nFor Swift Package Manager add the following package to your Package.swift:\n```swift\n.package(url: \"https://github.com/fredyshox/PageView.git\", .upToNextMajor(from: \"1.5.0\")),\n```\n\n### Carthage\n\n\nCarthage is also supported, add following line to Cartfile:\n```\ngithub \"fredyshox/PageView\" ~\u003e 1.5.0\n```\n\n## Demo\n\nDemo app for both iOS and watchOS is provided in `Examples/` directory.\n\n## Usage\n\n```swift\nimport PageView\n```\n\nPageView component is available as `HPageView` or `VPageView` depending on scroll direction (horizontal and vertical, respectively). To add paged view with 3 pages use following code:\n\n```swift\n@State var pageIndex = 0\n\n...\n\n// horizontal axis\nHPageView(selectedPage: $pageIndex) {\n    SomeCustomView()\n    AnotherCustomView()\n    AnotherCustomView()\n}\n\n// vertical axis\nVPageView(selectedPage: $pageIndex) {\n    SomeCustomView()\n    AnotherCustomView()\n    AnotherCustomView()\n}\n```\n\nBy default PageView fills all the available area, you can constrain it's size using `.frame(width:, height:)` view modifier.\n\n### Selected page binding\n\nDisplayed page can be programmatically controled using `Binding`. For example, you can change it, with animation effect using: \n\n```swift\nwithAnimation {\n  // page index is some State property, which binding was passes into PageView\n  self.pageIndex = 2\n}\n```\n\n### ForEach-style init\n\nPageView supports `ForEach`-like initialization, that is:\n\n```swift\n// integer ranges\nHPageView(selectedPage: $pageIndex, data: 0..\u003c5) { index in\n    SomeCustomView(withIndex: index)\n}\n\n// or collection of `Identifiable`\nlet identifiableArray: [SomeIdentifiableItem] = ...\nHPageView(selectedPage: $pageIndex, data: identifiableArray) { item in\n    SomeCustomView(withItem: item) \n}\n\n// or any other collection, by specifing id by key-path\nlet nonIdentifiableArray: [SomeNonIdentifiableItem] = ...\nHPageView(selectedPage: $pageIndex, data: nonIdentifiableArray, idKeyPath: \\.path.to.id) { item in\n    SomeCustomView(withItem: item) \n}\n```\n\n### Page switch threshold\n\nYou can also control minimum distance that needs to be scrolled to switch page, expressed in fraction of page dimension (width or height, depending on axis). This parameter is called `pageSwitchThreshold`, and must be in range from 0.0 to 1.0.\n\nFor iOS the default value is set to `0.3`, while on watchOS `0.5`.\n\n### Gesture type\n\nIf PageView gestures are intefering with gestures present on individual pages, PageView's gesture type can be changed by passing `PageGestureType`. Possible values: `.standard`, `.simultaneous`, `.highPriority` (default)\n\n```swift\nVPageView(selectedPage: $pageIndex, pageGestureType: .simultaneous) {\n    // views \n}\n```\n\n\n\n### Theme\n\nStyling of page control component can be customized by passing `PageControlTheme`. Customizable properties:\n\n* `backgroundColor`\n* `dotActiveColor`: active page dot color\n* `dotInactiveColor`: inactive page dot color\n* `dotSize`: size of page dot\n* `spacing`: spacing between dots\n* `padding`: padding of page control\n* `xOffset`: page control x-axis offset, used only in vertical mode\n* `yOffset`: page control y-axis offset, used only in horizontal mode\n* `opacity`: page control opacity in range from 0.0 (invisible) to 1.0 (opaque)\n* `alignment`: alignment of page control component (default: bottom-center in horizontal mode, center-leading in vertical mode)\n\n```swift\nlet theme = PageControlTheme(\n    backgroundColor: .white,\n    dotActiveColor: .black,\n    dotInactiveColor: .gray,\n    dotSize: 10.0,\n    spacing: 12.0,\n    padding: 5.0,\n  \txOffset: 8.0,\n    yOffset: -8.0,\n    opacity: 0.5,\n    alignment: Alignment(horizontal: .trailing, vertical: .top)\n)\n...\nVPageView(theme: theme) {\n    ...\n}\n```\n\nThere is also a built-in `PageControlTheme.default` style, mimicking `UIPageControl` appearance. To hide it completely use `PageControlTheme.invisible`.\n\n## API\n\n```swift\n// Horizontal page view\npublic struct HPageView\u003cPages\u003e: View where Pages: View {\n    public init(\n        selectedPage: Binding\u003cInt\u003e,\n        pageSwitchThreshold: CGFloat = .defaultSwitchThreshold,\n        pageGestureType: PageGestureType = .highPriority,\n        theme: PageControlTheme = .default,\n        @PageViewBuilder builder: () -\u003e PageContainer\u003cPages\u003e\n    )\n}\n\n// Vertical page view\npublic struct VPageView\u003cPages\u003e: View where Pages: View {\n    public init(\n        selectedPage: Binding\u003cInt\u003e,\n        pageSwitchThreshold: CGFloat = .defaultSwitchThreshold,\n        pageGestureType: PageGestureType = .highPriority,\n        theme: PageControlTheme = .default,\n        @PageViewBuilder builder: () -\u003e PageContainer\u003cPages\u003e\n    )\n}\n\npublic enum PageGestureType {\n    case standard, simultaneous, highPriority\n}\n\npublic struct PageControlTheme {\n    public var backgroundColor: Color\n    public var dotActiveColor: Color\n    public var dotInactiveColor: Color\n    public var dotSize: CGFloat\n    public var spacing: CGFloat\n    public var padding: CGFloat\n    public var xOffset: CGFloat\n    public var yOffset: CGFloat\n    public var opacity: Double\n    public var alignment: Alignment?\n}\n```\n\n\n\n## Screenshots\n\n![iOS example](./Images/PageView_iOS.png)\n\n![HPageView on watchOS](./Images/HPageView_watchOS.gif)\n\n![VPageView on watchOS](./Images/VPageView_watchOS.gif)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffredyshox%2FPageView","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffredyshox%2FPageView","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffredyshox%2FPageView/lists"}