iPages πŸ“– Quickly implement swipable page views in iOS

Related tags

Pagination iPages
Overview

iPages πŸ“–

Quickly implement swipable page views in iOS. πŸ“

Get Started | Examples | Customize | Install |

CI


Get Started

  1. Install iPages

  2. Add iPages to your project

import SwiftUI
import iPages

struct ContentView: View {
    var body: some View {
        iPages {
            Text("iPages πŸ€‘")
            Color.pink
        }
    }
}
  1. Customize your iPages

Examples

Marketing Materials πŸ’Έ

Use iGraphicsView to demo marketing slides.

import SwiftUI
import iPages
import iGraphics

struct ContentView: View {
    var body: some View {
        iPages {
            iGraphicsView(.first)
            iGraphicsView(.second)
            iGraphicsView(.third)
        }
    }
}


Shopping App πŸ›

If you want, you can pass in your own optional selection binding to iPages. Hide the bottom dots & add infinite scroll to remove context.

import SwiftUI
import iPages
import iGraphics

struct ContentView: View {
    @State var currentPage: Int = 0

    var body: some View {
        iPages(selection: $currentPage) {
            iGraphicsBox(.photo)
                .stack(3)
            iGraphicsBox(.card)
                .stack(2)
        }
        .hideDots(true)
        .wraps(true)
    }
}



Customize πŸŽ€

iPages takes a trailing view builder of ordered views. You can also optionally pass in your own page index binding called selection:, to let you build your own page control, or however you want to use it. iPages supports a variety of custom modifiers. All customizations are built into our modifiers.

Example: Change the dot colors, enable infinite wrap & hide dots for single page views with the following code block:

iPages(selection: $currentPage) {
    Text("πŸ‘")
}
.dotsTintColors(currentPage: Color, otherPages: Color)
.wraps(true)
.dotsHideForSinglePage(true)
.navigationOrientation(.vertical)

Use our exhaustive input list to customize your views.

Modifier or Initializer Description
πŸ‘·β€β™€οΈ .init(content:) Initializes the page πŸ“ƒ πŸ“– view.
πŸ‘·β€β™‚οΈ .init(selection:content:) Initializes the page πŸ“ƒ πŸ“– view with a selection binding.
⏺ .hideDots(_:) Modifies whether or not the page view should include the standard page control dots. (β€’β€’β€’β€’)
πŸ”„ .wraps(_:) Modifies whether or not the page view should restart at the beginning πŸ” when swiping past the end (and vise-versa)
1️⃣ .dotsHideForSinglePage(_:) Modifies whether the page dots are hidden when there is only one page. 1️⃣ ‡️
🎨 .dotsTintColors(currentPage:otherPages:) Modifies tint colors 🟑 🟒 πŸ”΄ 🟣 to be used for the page dots.
πŸ”˜ .dotsBackgroundStyle(_:) Modifies the background style βšͺ️ πŸ”˜ of the page dots.
πŸ”ƒ .dotsAllowContinuousInteraction(_:) Modifies the continuous interaction settings of the dots. πŸ”„
↔️ .dotsAlignment(_:) Modifies the alignment of the page dots. πŸ‘† πŸ‘‡
↕️ .navigationOrientation(_:) Modifies the navigation orientation of the page view. ↔️ ↕️
🦿 .disableBounce(_:) Disables the bounce settings of the page view. This is especially useful for scroll views.
↔️ .interPageSpacing(_:) Modifies the spacing between the pages. ↔️
πŸŽ₯ .animated(_:) Modifies whether the the pages animate the slide if the selection binding changes. πŸŽ₯

Install

Use the Swift package manager to install. Find instructions here πŸ˜€

Help

As always, if you have any questions about iPages, we are available 24/7 to help.

Reach us at
πŸ“ž +1 (415) 735-4464 Call
πŸ“§ [email protected] Email
πŸ“² +1 (415) 735-4464 Text
Comments
  • Crush and Swipes

    Crush and Swipes

    iPages {
                ForEach(0..<10) {
                    Text("Index \($0)")
                }
            }
    

    Will swipe itself

    and if I set array in forEach I get error:

    Fatal error: Index out of range: file Swift/ContiguousArrayBuffer.swift, line 444

    Π‘Π½ΠΈΠΌΠΎΠΊ экрана 2020-11-02 Π² 15 53 05
    opened by kfoau9h39 3
  • Can't use custom Views

    Can't use custom Views

    Hello!

    Absolutely love the look of this but I've been struggling to get it working with custom views. I keep getting an error saying Cannot convert value of type someCustomView to closure result type '[UIViewController]'

    Is there something I'm doing wrong?

    Here's a screenshot of my code too: Screenshot 2020-10-22 at 12 16 30

    Thanks in advance!

    opened by callaghanjames 3
  • Selection binding brakes swiping

    Selection binding brakes swiping

    That's what happens when I try to scroll between several pages with selection binding:

    Video: https://streamable.com/aiva4p

    Code:

    struct TestView: View {
        @State var selectedIdx = 0
    
        var body: some View {
            iPages(selection: $selectedIdx) {
                Color.red
                Color.blue
                Color.yellow
            }
            .onChange(of: selectedIdx) { value in
                print("INDEX: \(value)")
             }
        }
    }
    
    opened by planecore 2
  • Change state in parent view of iPage will trigger unwanted animation

    Change state in parent view of iPage will trigger unwanted animation

    Hi there, thanks for the quick fix yesterday now it works like charm!

    Just encounter another issue, when I change the state of iPage parents view, iPage will trigger an unwanted animation.

    Example code:

    struct TabViewParentView: View {
        @State var selectedIndex: Int = 0
        @State var tabViewIsHidden: Bool = false
    
        var body: some View {
            ZStack {
                iPages(selection: $selectedIndex) {
                    ProfileView()
                    SecondView()
                    ThirdView()
                }
                .hideDots(true)
    
                VStack {
                    Button {
                        tabViewIsHidden = !tabViewIsHidden
                    } label: {
                        Text("HELLO THERE!")
                    }
    
                    Spacer()
    
                    Text("TEXT")
                        .foregroundColor(.white)
                        .opacity(tabViewIsHidden ? 0 : 1)
                }
            }
        }
    
    }
    

    When the button pressed and @State tabViewIsHidden was changed, the iPage will scroll to the same page with animation:

    Demo:

    Screen Recording 2020-10-27 at 1 30 29 pm

    I wonder if it is possible to prevent this? This is needed for making my custom tab view control, I was making an auto dismissed tab view control, but when I change the state, this unwanted animation was triggered.

    opened by DechengMa 2
  • After putting view inside iPage {}, change state will not update the child view

    After putting view inside iPage {}, change state will not update the child view

    Hi, This is a nice package and quite easy to use.

    Just encounter the issue: after putting my custom view inside an iPage view, all the child view lost the ability to react to state changes:

    Example:

    struct SetUpView: View {
        @State var foo: String = "Hello"
    
        var body: some View {
            ZStack {
                Text("\(foo)")
    
                Button("Button") {
                    foo = "123"
                }
            }
            .ignoresSafeArea(.all)
        }
    }
    

    After putting this view inside iPage, when the button clicked, the text won't get changed.

                iPages {
                    SetUpView()
                }
                .ignoresSafeArea(.all)
    

    and it works normal when put outside the iPage block.

    Any solution?

    opened by DechengMa 2
  • Customised views cannot be passed in iPages Initializer

    Customised views cannot be passed in iPages Initializer

    I'm trying out iPages however I encountered the following issue.

    It's a very basic usage - one master view initializes iPages and two subviews A and B.

    MasterView.swift

    import SwiftUI
    import iPages
    
    struct MasterView: View {
        @State var currentPage: Int = 0
        var body: some View {
            iPages([SubViewA(), SubViewB()], currentPage: $currentPage)
        }
    }
    

    SubViewA.swift

    import SwiftUI
    
    struct SubViewA: View {
        var body: some View {
            Text("this is subview A")
        }
    }
    

    SubViewB.swift

    import SwiftUI
    
    struct SubViewB: View {
        var body: some View {
            Text("this is subview B")
        }
    }
    

    The above code does not compile with the unhelpful error as follows. image

    Environment XCode: Version 12.0.1 macOS: Catalina 10.15.7

    Please can anyone suggest if I'm doing anything incorrect or there is a bug somewhere in the library? Thanks in advance!

    opened by neptunezxn 2
  • Added custom responding page event

    Added custom responding page event

    Added a way to customize willTransitionTo and didFinishAnimationg delegate method. Please check it out and accept the request if you like it. πŸ˜†

    example

    iPages {
        Text("iPages πŸ€‘")
        Color.pink
    }
    .didFinishAnimationg { _, _, _, _ in
        print("Insert didFinishAnimating action code here")
    }
    .willTransitionTo { (pageViewController, viewControllers) in
        print("Insert willTransitionTo action code here")
    }
    

    It is implemented so that it is not expressed in "page view initializes" for readability when writing code.πŸ˜€

    image

    opened by devyhan 1
  • Examples need to be relocated

    Examples need to be relocated

    Currently the example file adds two dependencies to every project that aren’t needed.

    You should’ve created a new folder called β€œExample” at the root of the repo with an example Xcode project.

    opened by planecore 1
  • iPages Review

    iPages Review

    Swiping is dope. Super natural spring. I really fuck with that. Similar to the other repositories, all comments here are ease of use or aesthetic related. The engine runs well!

    1. Page number confusion. I wanted to see if currentPage was zero indexed or 1 indexed and it wasn't in the documentation. Easy thing to add.

    2. The app crashes when you enter a negative current page. Consider making current page an unsigned int, so change Int to UInt. I think that makes more sense in this context bc you could never have a negative page count.

    3. The app crashes when you enter a non-valid current page. Thoughts on just making it instead go to the nearest page? If you enter page 9 and there are 6 pages just send it to page six.

    4. An aesthetic point, but I did very much expect some dots at the bottom of the view. At least something to indicate the type of element I was dealing with. My first step was to I look at the init's & the modifiers to try to see if I was simply missing that option and didn't see anything.

    5. It was really difficult to figure out the default height and width of the view. It was also difficult to figure out if that height and width was inherited from the subviews. Unsure the best way to communicate that information, but definitely confusing.

    6. We should toss in a sexy dummy view that'd be cool.

    opened by AlexFine 0
  • Uncaught Exception Crash

    Uncaught Exception Crash

    Stack

    
    2022-08-22 19:46:00.438076-0400 tweetmarks[43546:3140745] *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x11dc0e5f0> should have parent view controller:<UIPageViewController: 0x10621aa00> but requested parent is:<UIPageViewController: 0x1061fd200>'
    *** First throw call stack:
    (0x18a4a9288 0x1a31d8744 0x18a500390 0x18ca49dd0 0x18d1b6774 0x18d1b6958 0x18d1b6c50 0x104a95418 0x104a95530 0x1928ae4e8 0x19218a300 0x19223a704 0x192115c10 0x1920f1564 0x1920b31ac 0x1920e9bd4 0x1bca3bb18 0x1bca3b508 0x1bca3a318 0x192061124 0x192d34da8 0x192052784 0x19205e618 0x1920570f8 0x192050110 0x19204f1a4 0x192d35cb0 0x19215c798 0x19204d5b4 0x19204d640 0x19213d540 0x1b9133a10 0x19204d4d8 0x19204d7a8 0x18a4510c4 0x18a420080 0x18a41b13c 0x18a42ebc8 0x1a6599374 0x18cda2b58 0x18cb24090 0x192288f24 0x1921b6e08 0x1921980f4 0x10470c4a8 0x10470d3bc 0x105d99da4)
    libc++abi: terminating with uncaught exception of type NSException
    dyld4 config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/Developer/usr/lib/libBacktraceRecording.dylib:/Developer/usr/lib/libMainThreadChecker.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
    *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x11dc0e5f0> should have parent view controller:<UIPageViewController: 0x10621aa00> but requested parent is:<UIPageViewController: 0x1061fd200>'
    terminating with uncaught exception of type NSException
    
    
    opened by arbyruns 0
  • Error when try to use combined with ForEach

    Error when try to use combined with ForEach

    Hello, I'm trying to fill iPages using ForEach but I get this error. "Thread 1: Fatal error: Index out of range", on line 78 of PageViewController.swift of the iPages project.

    This is the correct code to use or not support dynamic views ?

    Thanks

                        iPages {
                            ForEach(notifications, id: \.self) { notification in
                                VStack {
                                    Text(notification.subject)
                                        .font(.title2)
                                        .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                                    Text(notification.kind)
                                        .font(.title2)
                                    Text(notification.updatedAt)
                                        .font(.title3)
                                }
                            }
                        }
    
    opened by jgiunta 1
  • Setting disableBounce to true breaks switching tab via binding

    Setting disableBounce to true breaks switching tab via binding

    If you set disableBounce to true it's no longer possible to change the selected tab via the binding.

    Edit: only the first and last tab aren't accessible via the binding. The navigation to tabs between them is still working.

    Interactive example to reproduce:

    struct ContentView: View {
        @State var selection = 0
        @State var bounceDisabled = false
        var body: some View {
            VStack {
                Button("Tab 0", action: { selection = 0 })
                Button("Tab 1", action: { selection = 1 })
                Button("Toggle bounce", action: { bounceDisabled.toggle() } )
                Text("Selected tab: \(selection)")
                Text(bounceDisabled ? "Bounce disabled" : "Bounce enabled")
                
                iPages(selection: $selection) {
                    Text("Tab 0")
                    Text("Tab 1")
                }
                .disableBounce(bounceDisabled)
            }
        }
    }
    
    opened by theblaggy 0
  • Eliminates some UI elements if inside VStacks

    Eliminates some UI elements if inside VStacks

    This is a bit of a weird one an potentially not iPages related. I'm curious if you can recreate this issue.

    I was using the default apple PageTabViewStyle but saw this library and gave it a shot. My app has buttons that show up based on if statements. This worked fine with PagesTabView, but upon adding iPages, the buttons inside if statements disappear. If I remove the if statement the buttons pop back up.

    Not quite sure what the issue is. I've attached my ContentView.swift file below, with most of my code removed for clarity.

    ` import SwiftUI import HealthKit import HealthKitUI import iPages

    class SummaryHolder: ObservableObject { @Published var theSummary: HKActivitySummary = HKActivitySummary(); }

    struct ContentView: View { var body: some View { iPages{ ZStack{ LinearGradient(gradient: Gradient(colors: [.black, Color("darkBlue")]), startPoint: .topLeading, endPoint: .bottomTrailing).ignoresSafeArea() VStack { VStack { if movePercent >= 50 { Button(action: /@START_MENU_TOKEN@//@PLACEHOLDER=Action@/{}/@END_MENU_TOKEN@/) { DispenseButton(title: "One Spin", textColor: .blue, backgroundColor: .white) } }

                    if movePercent >= 75 {
                    Button(action: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Action@*/{}/*@END_MENU_TOKEN@*/) {
                        DispenseButton(title: "Two Spins",
                                       textColor: .blue,
                                       backgroundColor: .white)
                    }
                    }
                    
                    if movePercent >= 100 {
                    Button(action: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Action@*/{}/*@END_MENU_TOKEN@*/) {
                        DispenseButton(title: "Three Spins",
                                       textColor: .blue,
                                       backgroundColor: .white)
                    }
                    }
                    
                    if movePercent < 50 {
                        Image(systemName: "exclamationmark.triangle.fill") .renderingMode(.original)
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 180, height: 180, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
                        
                        Text("Get moving and try again later").font(.system(size: 20, weight: .bold, design: .default))
                            .foregroundColor(.white)
                            .padding().multilineTextAlignment(.center)
                    }
                }
                Spacer()
            }
        }
            Text("Add Bluetooth Menu here").tabItem {
                    Image(systemName: (selected == 0 ? "sun.fill" : "sun"))
                    Text("Home")
                }
        }.hideDots(false).edgesIgnoringSafeArea(.all)
    }
    

    }

    struct ContentView_Previews: PreviewProvider { static var previews: some View { Group { ContentView() } } } `

    opened by CaptainZ1 2
Releases(0.0.13)
Owner
Benjamin Sage
iOS frontend dev using SwiftUI πŸ€‘
Benjamin Sage
πŸ“– A simple, highly informative page view controller

TL;DR UIPageViewController done properly. ⭐️ Features Simplified data source management & enhanced delegation. Dynamically insert & remove pages. Infi

UI At Six 1.8k Jan 5, 2023
This is a selection of custom page controls to replace UIPageControl

PageControls This is a selection of custom page controls to replace UIPageControl, inspired by a dribbble found here. The appearance (color, size, # o

Kyle Zaragoza 1k Jan 2, 2023
πŸ’₯ Beautiful, animated and highly customizable UIPageControl alternative for iOS.

PageControl Requirements iOS 9.0+ Xcode 7.0+ Installation CocoaPods: Add folowing line to Podfile and run 'pod instal'. pod 'Sevruk-PageControl' Or j

Sevruk Development 30 May 2, 2022
Swipable tab and menu View and ViewController.

SwipeMenuViewController Overview SwipeMenuViewController provides SwipeMenuView and SwipeMenuViewController. This is very useful to build swipe-based

Yusuke Morishita 1.2k Dec 29, 2022
Reading animation allows you to click on the different page numbers and accordingly it will animate page changes in a cool way. It has a very attractive UI and is very easy to use.

Reading Animation Cool Reading Animation in iOS written in Swift. Preview Table of content :- Description How to add in your project Requirement Licen

MindInventory 42 Oct 4, 2022
A PageView Swiping to the left will go to previous page and swiping to the right will go to next page

PageView This package creates a PageView. Swiping to the left will go to previous page and swiping to the right will go to next page. You can find how

null 0 Oct 20, 2021
Apple watch app - a note taking app with few views including credit page.

Thanks for checking out my SwiftUI Apple Watch project. My first ever apple watch app. This is a note taking app with few views including credit page.

Timal Pathirana 1 Jun 18, 2022
Highly configurable iOS Alert Views with custom content views

NYAlertViewController NYAlertViewController is a replacement for UIAlertController/UIAlertView with support for content views and UI customization. Fe

Nealon Young 609 Nov 20, 2022
Protocol to handle initial Loadings, Empty Views and Error Handling in a ViewController & views

StatusProvider Protocol to handle initial Loadings, Empty Views and Error Handling in a ViewController & views CocoaPods Podfile pod 'StatusProvider'

Mario Hahn 887 Dec 22, 2022
Swift-picker-views - inline single and multi picker views for UIKit. Without tableview! Easy and simple

swift-picker-views Inline single and multiple picker views for UIKit. No tablevi

IBRAHIM YILMAZ 2 Jan 31, 2022
A Swift utility to make updating table views/collection views trivially easy and reliable.

ArrayDiff An efficient Swift utility to compute the difference between two arrays. Get the removedIndexes and insertedIndexes and pass them directly a

Adlai Holler 100 Jun 5, 2022
Luminous provides you a lot of information about the system and a lot of handy methods to quickly get useful data on the iOS platform.

Luminous Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 8+ Swift 5 Xcode 1

Andrea Mario Lufino 324 Nov 27, 2022
Library for iOS Camera API. CameraKit helps you add reliable camera to your app quickly.

CameraKit helps you add reliable camera to your app quickly. Our open source camera platform provides consistent capture results, service that scales, and endless camera possibilities.

CameraKit 628 Dec 27, 2022
Quickly reproduce the dropdown UIPickerView / ActionSheet functionality on iOS.

ActionSheetPicker-3.0 Important update Now I fixed most of the things and merge PR' (thanks to ). I did much work to support this library from iOS 5.

Petr Korolev 3.4k Dec 21, 2022
Simple camera application for iOS that uploads pictures to WebDAV server or Dropbox quickly. Available on the AppStore.

Upupu Simple camera application for iOS that uploads pictures to WebDAV server or Dropbox quickly. Also available on the AppStore. Features Easy and f

Xcoo 65 Nov 15, 2022
Blocks Based Bluetooth LE Connectivity framework for iOS/watchOS/tvOS/OSX. Quickly configure centrals & peripherals, perform read/write operations, and respond characteristic updates.

ExtendaBLE Introduction ExtendaBLE provides a very flexible syntax for defining centrals and peripherals with ease. Following a blocks based builder a

Anton 94 Nov 29, 2022
Luminous provides you a lot of information about the system and a lot of handy methods to quickly get useful data on the iOS platform.

Luminous Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 8+ Swift 5 Xcode 1

Andrea Mario Lufino 324 Nov 27, 2022
iOS library for quickly displaying images while scrolling

Fast Image Cache is an efficient, persistent, andβ€”above allβ€”fast way to store and retrieve images in your iOS application. Part of any good iOS applic

Path Mobile Inc Pte. Ltd. 8.2k Jan 9, 2023
An iOS app that lets user quickly jot down thoughts with Markdown support

Thoughtless An iOS app that lets user quickly jot down thoughts with Markdown support. Description Perhaps you are often in a situation where you want

Yohannes Wijaya 25 May 24, 2022
Open source SDK to quickly integrate subscriptions, stop worring about code maintenance, and getting advanced real-time data. Javascript / iOS glue framework

Open source SDK to quickly integrate subscriptions, stop worring about code maintenance, and getting advanced real-time data. Javascript / iOS glue framework

glassfy 5 Nov 7, 2022