🚀 Elegant Pager View fully written in pure SwiftUI.

Overview

PagerTabStripView

build and test Platform iOS Swift 5 compatible Carthage compatible CocoaPods compatible License: MIT

Made with ❤️ by Xmartlabs team. XLPagerTabStrip for SwiftUI!

Introduction

PagerTabStripView is the first pager view built in pure SwiftUI. It provides a component to create interactive pager views which contains child views. It allows the user to switch between your views either by swiping or tapping a tab bar item.

Unlike Apple's TabView it provides:

  1. Flexible way to fully customize pager tab views.
  2. Each pagerTabItem view can be of different type.
  3. Bar that contains pager tab item is placed on top.
  4. Indicator view indicates selected child view.
  5. onPageAppear callback to easily trigger actions when page is selected.
  6. Ability to update pagerTabItem according to highlighted, selected, normal state.

..and we've planned many more functionalities, we have plans to support each one of the XLPagerTabStrip styles.

Usage

Creating a page view is super straightforward, you just need to place your custom tab views into a PagerTabStripView view and apply the pagerTabItem( _: ) modifier to each one to specify its navigation bar tab item.

import PagerTabStripView

struct MyPagerView: View {

    var body: some View {

        PagerTabStripView() {
            MyFirstView()
                .pagerTabItem {
                    TitleNavBarItem(title: "Tab 1")
                }
            MySecondView()
                .pagerTabItem {
                    TitleNavBarItem(title: "Tab 2")
                }
            if User.isLoggedIn {
                MyProfileView()
                    .pagerTabItem {
                        TitleNavBarItem(title: "Profile")
                    }
            }
        }

    }
}


To specify the initial selected page you can pass the selection init parameter.

struct MyPagerView: View {

    @State var selection = 1

    var body: some View {
        PagerTabStripView(selection: $selection) {
            MyFirstView()
                .pagerTabItem {
                    TitleNavBarItem(title: "Tab 1")
                }
            ...
            ..
            .
        }
    }
}

As you may've already noticed, everything is SwiftUI code, so you can update the child views according to SwiftUI state objects as shown above with if User.isLoggedIn.

Customize pager style

PagerTabstripView provides 3 different ways to show the views. You have the ability to select it and customize some aspects of each one using the pagerTabStripViewStyle modifier.

Normal style

This is likely the most common pager type. The customizable settings are:

  • Spacing between navigation bar items
  • Navigation bar height
  • Indicator bar height
  • Indicator bar color
struct PagerView: View {

	var body: some View {
		PagerTabStripView(selection: 1) {
			MyView()
				.pagerTabItem {
					TitleNavBarItem(title: "Tab 1")
				}
			AnotherView()
				.pagerTabItem {
					TitleNavBarItem(title: "Tab 2")
				}
			if User.isLoggedIn {
				ProfileView()
					.pagerTabItem {
						TitleNavBarItem(title: "Profile")
                    }
			}
		}
        .pagerTabStripViewStyle(.normal(indicatorBarColor: .gray, tabItemSpacing: 0, tabItemHeight: 50))
	}
}

In this example, we add some settings like the tab bar height, indicator bar color and indicator bar height. Let's watch how it looks!

Bar style

This style only shows a bar that indicates the current view controller. The customizable settings are:

  • Spacing between navigation bar items
  • Indicator bar height
  • Indicator bar color

Segmented style

This style uses a Segmented Picker to indicate which view is being displayed. You can indicate the selected color, its padding and if you want it setted in the toolbar.

Navigation bar

The navigation bar supports custom tab items. You need to specify its appearance creating a struct that implements View protocol.

For simplicity, we are going to implement a nav bar item with only a title. You can find more examples in the example app.

struct TitleNavBarItem: View {
    let title: String

    var body: some View {
        VStack {
            Text(title)
                .foregroundColor(Color.gray)
                .font(.subheadline)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.white)
    }
}

Customize selected and highlighted items

You can define the style of your nav items when they are selected or highlighted by conforming PagerTabViewDelegate protocol in your nav item view.

In the following example we change the text and background color when the tab is highlighted and selected.

private class NavTabViewTheme: ObservableObject {
    @Published var textColor = Color.gray
    @Published var backgroundColor = Color.white
}

struct TitleNavBarItem: View, PagerTabViewDelegate {
    let title: String
    @ObservedObject fileprivate var theme = NavItemTheme()

    var body: some View {
        VStack {
            Text(title)
                .foregroundColor(theme.textColor)
                .font(.subheadline)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(theme.backgroundColor)
    }

    func setState(state: PagerTabViewState) {
        switch state {
        case .selected:
            self.theme.textColor = .blue
            self.theme.backgroundColor = .lightGray
        case .highlighted:
            self.theme.textColor = .pink
        default:
            self.theme.textColor = .gray
            self.theme.backgroundColor = .white
        }
    }
}

onPageAppear modifier

onPageAppear callback allows you to trigger some action when a page view gets selected, either by scrolling to it or tapping its tab. This modifier is applied only to its associated page view.

struct PagerView: View {

    var body: some View {
        PagerTabStripView(selection: 1) {
            MyView(model: myViewModel)
                .pagerTabItem {
                    TitleNavBarItem(title: "Tab 1")
                }
                .onPageAppear {
                    model.reload()
                }
        }
        .pagerTabStripViewStyle(.normal(indicatorBarHeight: 2, indicatorBarColor: .gray, tabItemSpacing: 0, tabItemHeight: 50))
    }
}

Examples

Follow these 3 steps to run Example project

  • Clone PagerTabStripView repo.
  • Open PagerTabStripView workspace.
  • Run the Example project.

Installation

CocoaPods

To install PagerTabStripView using CocoaPods, simply add the following line to your Podfile:

pod 'PagerTabStripView', '~> 2.0'

Carthage

To install PagerTabStripView using Carthage, simply add the following line to your Cartfile:

github "xmartlabs/PagerTabStripView" ~> 2.0

Requirements

  • iOS 14+
  • Xcode 12.X

Author

Getting involved

  • If you want to contribute please feel free to submit pull requests.
  • If you have a feature request please open an issue.
  • If you found a bug or need help please check older issues and threads on StackOverflow (Tag 'PagerTabStripView') before submitting an issue.

Before contribute check the CONTRIBUTING file for more info.

If you use PagerTabStripView in your app We would love to hear about it! Drop us a line on Twitter.

Comments
  • Add: Custom case for fully access to indicator and navigationBar customization

    Add: Custom case for fully access to indicator and navigationBar customization

    Add infinite possibilities to customize the Indicator Bar:

    • Circle
    • Image
    • Animated View
    • Async View
    • SF Symbol
    • Text
    • Or any other View the user likes with any customization!

    Usage:

    .pagerTabStripViewStyle(
        .custom(
            indicator: {
                AnyView(
                    Circle()
                        .foregroundColor(.red)
                        .frame(height: 20)
                )
            }
        )
    )
    
    opened by MojtabaHs 6
  • Can't find 4.0.0

    Can't find 4.0.0

    -> PagerTabStripView (3.2.0) PagerTabStripView allows navigating through pages using a custom navigation bar in SwiftUI. pod 'PagerTabStripView', '~> 3.2.0'

    • Homepage: https://github.com/xmartlabs/PagerTabStripView
    • Source: https://github.com/xmartlabs/PagerTabStripView.git
    • Versions: 3.2.0, 3.1.1, 3.1.0, 3.0.0, 2.1.0, 2.0.0, 1.0.1, 1.0.0 [cocoapods repo]

    pod --version 1.11.3

    Can't find 4.0.0

    opened by GitHubZebra 2
  • Add: Custom pager animation

    Add: Custom pager animation

    Thanks for providing the great library!

    Fixes #issue(s) .

    • no issue

    Changes proposed in this request:

    • Add custom pager animation

    Here's examples.

    1. Transition to page even more slowly
      .pagerTabStripViewStyle(
                .custom(
                    tabItemHeight: 48,
                    ...
                    pagerAnimation: .interactiveSpring(response: 1.5, dampingFraction: 1.00, blendDuration: 0.25)
                )
            )
    

    https://user-images.githubusercontent.com/52638834/192090681-c057637f-87f1-4c3e-8730-2fb90f146e40.mov

    1. Make quick transitions ( means no animation )
      .pagerTabStripViewStyle(
                .custom(
                    tabItemHeight: 48,
                    ...
                    pagerAnimation: .none
                )
            )
    
    

    https://user-images.githubusercontent.com/52638834/192090620-3c91a5b2-4712-40f3-bd49-6654ef1292d1.mov

    I hope to get a good response from you! Thanks!

    opened by coffmark 2
  • Is there a way to customize the indicator bar length?

    Is there a way to customize the indicator bar length?

    Is your feature request related to a problem? Please describe. I would like way to customize the indicator bar length in a scrollableBarButton

    Describe the solution you'd like In addition to indicatorBarHeight and indicatorBarColor, maybe we can have an indicatorBarLength as well

    Describe alternatives you've considered I tried to use the custom PagerStyle, but wasn't able to figure out how to get both a scrollable bar and indicator height

    Something like this is what I'm looking for. Notice that the indicator goes beyond the title for a bit on both sides. Simulator Screen Shot - iPhone 11 Pro - 2022-03-28 at 00 03 51 Simulator Screen Shot - iPhone 11 Pro - 2022-03-28 at 00 04 13

    opened by skywalkerdude 2
  • Add leading and Trailing padding to the scrollable Segment Tab view

    Add leading and Trailing padding to the scrollable Segment Tab view

    I was trying to add the Leading and trailing padding to the scrollable Tab Title view, but if I add it, it gets applied to the entire view and not just the TabStrip Title view. I am not able to modify the code because of the private methods. Can you please fix this?

    opened by harshadkhedekar 2
  • Bug in iOS 15

    Bug in iOS 15

    Hello, I have an issue when using scrollable in iOS 15. That issue is when I move to another view using navlink then back again to the view that have pagertabstripview. the scrollable doesn't show like below. image

    opened by reinaldoriant 2
  • Swipe to other tab view not working

    Swipe to other tab view not working

    Hi, its great package

    i have problem when to tried swipe between tab, i was using ScrollView instead List. thankyou

    ......
    struct ContentView: View {
        var body: some View {
            VStack {
                PagerTabStripView(selection: $selectionIndex) {
                    ListData()
                    ListData()
                }
                ......  
    
    ......
    struct ListData: View {
        var body: some View {
            ScrollView {
                VStack {
                ......
    
    opened by ghost 2
  • How to make sticky Navigation Title bar in scrollview

    How to make sticky Navigation Title bar in scrollview

    Inside scrollview I Have an image view on the top and below is navigation Pager view . How to make navigation title bar pinned on the top? Can you pleased guide me

    opened by naveedmcs 1
  • iOS 14 scrollableBarButton scroll bar still disappears in a tab view

    iOS 14 scrollableBarButton scroll bar still disappears in a tab view

    Repost of https://github.com/xmartlabs/PagerTabStripView/issues/63 since it looks like it's still happening.

    Describe the bug On iOS14 builds, sometimes the scroll bar disappears

    To Reproduce Steps to reproduce the behavior:

    1. Replace ContentView in the Example app with:
    import SwiftUI
    import PagerTabStripView
    
    struct ContentView: View {
        
        var body: some View {
            NavigationView {
                TabView {
                    InstagramView().tabItem {Text("InstagramView").maxWidth()}.hideNavigationBar()
                    TwitterView().tabItem {Text("TwitterView").maxWidth()}.hideNavigationBar()
                    YoutubeView().tabItem {Text("YoutubeView").maxWidth()}.hideNavigationBar()
                    SegmentedView().tabItem {Text("SegmentedView").maxWidth()}.hideNavigationBar()
                    BarStyleView().tabItem {Text("BarStyleView").maxWidth()}.hideNavigationBar()
                }
            }
        }
    }
    
    extension View {
        
        func hideNavigationBar() -> some View {
            self
                .navigationBarTitle("", displayMode: .inline)
                .navigationBarHidden(true)
        }
        
        func maxWidth(alignment: Alignment = .center) -> some View {
            self.frame(minWidth: .zero, idealWidth: .infinity, maxWidth: .infinity, alignment: alignment)
        }
    }
    
    1. Run Example App
    2. Click on "TwitterView"
    3. Click on "Short"
    4. Click on "SegmentedView
    5. Click on "BarStyleView""
    6. Click back to "TwitterView"
    7. Click on "Medium width"
    8. Observe the bar disappear

    Expected behavior Scroll bar should not run away

    Screenshots See video in Additional Context section

    Versions (please complete the following information):

    • Xcode: 13.2.1
    • Device: iPhone 11 Pro Simulator
    • OS: iOS 14.5
    • Library version: 3.0.0

    Additional context Bug is reproducible in this branch: https://github.com/skywalkerdude/PagerTabStripView/blob/tabviewbug/Example/Shared/Additional%20Example%20Source%20Code/ContentView.swift

    https://user-images.githubusercontent.com/1427524/148024607-f7a38844-48d1-4ee9-9d27-ebecc0717966.mov

    opened by skywalkerdude 1
  • Swipe to back animation bug

    Swipe to back animation bug

    Describe the bug When a user makes a swipe gesture instead of a "back" button in the navigation bar, he will see unwanted swipe animations

    To Reproduce Steps to reproduce the behavior:

    1. Go to the example app
    2. Click on the first scrollable style button
    3. Try swipe to back gesture
    4. See the bug

    Versions (please complete the following information):

    • Xcode: 13.2
    • Device: iPhone13
    • OS: iOS 15.2
    • Lbrary version 3.1.0

    https://user-images.githubusercontent.com/94690815/146549473-5178eb7f-505c-4369-a593-0dc4e1683b7b.mov

    opened by alinless 1
  • Where is `TitleNavBarItem`? Compilation fails.

    Where is `TitleNavBarItem`? Compilation fails.

    Compilation fails due to lack of symbol TitleNavBarItem.

    To Reproduce Steps to reproduce the behavior:

    1. Run the first code example in README.

    Expected behavior Running.

    Screenshots Compile error.

    Versions (please complete the following information):

    • Xcode: 13.1
    • Device: Simulator
    • OS: iOS15
    • Lbrary version 3.1.0
    opened by hoon-prestolabs 1
  • '.isSelected' accessibility trait on the selected NavBarItem

    '.isSelected' accessibility trait on the selected NavBarItem

    Hello, I am using this package in an app and I realised that the active NavBarItem isn't recognized as selected by VoiceOver. It would be nice to add the .isSelected accessibility trait to the selected NavBarItem.

    I would propose something like this on the NavBarItem button:

    .accessibilityAddTraits(id == selection ? .isSelected : [])
    

    I don't think it's possible to do it from outside the package, I tried dynamically adding the trait to the pagerTabItem according to the $selection binding, like this:

    .pagerTabItem {
        Text("Any title")
         .frame(maxWidth: .infinity, maxHeight: .infinity)
         .accessibilityAddTraits(currentTab == 0 ? .isSelected: [])
    }
    

    But I think the view set in here is not redrawn, the PagerTabStripView will only draw the one received on initialisation.

    opened by marco-mattei-mo 0
  • Refactor code, solve several issues

    Refactor code, solve several issues

    Fixes #issue(s) .

    Changes proposed in this request:

    • Selection value now can be any hashable type
    • Layout protocol use to arrange subviews in scrollable and non-scrollable navbar items. No longer need to use geometry reader to get the tab size to position the indicator. Simplifies a lot the base code.
    opened by mtnbarreto 4
  • Is it possible for optional swipe for pagerTabItem?

    Is it possible for optional swipe for pagerTabItem?

    I know that the PagerTabStripView is able to control whether it is scrollable or not. It is possible to control TabItem scrollable? Thank you P.s, I would like to use scrollable PagerStyle and disable the scroll by conditional check.

    opened by lclronald 0
  • cannot swipe if PagerTabStripView in another PagerTabStripView

    cannot swipe if PagerTabStripView in another PagerTabStripView

    Is your feature request related to a problem? Please describe. My use case is my page have 2 levels, one for main-categories: A, B, C, and one for sub-categories: B1, B2, B3 something like that: A is some view B is PagerTabStripView with 3 pages: B1, B2, B3 (both are some view) C is some view I can swipe from A to B, but I cant swipe from B1 to A, and I can swipe from C to B, but I cant swipe from B3 to C

    Describe the solution you'd like I can swipe from B1 to A, and I can swipe from B3 to C

    Describe alternatives you've considered none

    Additional context none

    opened by fso-msrl 1
  • Is it easily possible to also animate the [scrollableBarButton - indicatorBar ] as oppose to making it snappy?

    Is it easily possible to also animate the [scrollableBarButton - indicatorBar ] as oppose to making it snappy?

    Hi, thank you for the project.

    Is it easily possible to also animate the indicatorBar for the style scrollableBarButton as the index changes as oppose to making it snappy? iOS 15

    I am refering to the blue bar below each tab.

    Screen Shot 2022-10-06 at 11 31 26 am

    Thank you.

    opened by waelsaad 0
Releases(3.2.0)
Owner
xmartlabs
xmartlabs
🔍 Awesome fully customize search view like Pinterest written in Swift 5.0 + Realm support!

YNSearch + Realm Support Updates See CHANGELOG for details Intoduction ?? Awesome search view, written in Swift 5.0, appears search view like Pinteres

Kyle Yi 1.2k Dec 17, 2022
Creating a simple selectable tag view in SwiftUI is quite a challenge. here is a simple & elegant example of it.

SwiftUI TagView Creating a simple selectable tag view in SwiftUI is quite a challenge. here is a simple & elegant example of it. Usage: Just copy the

Ahmadreza 16 Dec 28, 2022
ElongationPreview is an elegant UI push-pop style view controller

ElongationPreview is an elegant UI push-pop style view controller

Ramotion 886 Dec 19, 2022
A beautiful radar view to show nearby items (users, restaurants, ...) with ripple animation, fully customizable

HGRippleRadarView Example To run the example project, clone the repo, and run pod install from the Example directory first. This project is inspired b

Hamza Ghazouani 352 Dec 4, 2022
TSnackBarView is a simple and flexible UI component fully written in Swift

TSnackBarView is a simple and flexible UI component fully written in Swift. TSnackBarView helps you to show snackbar easily with 3 styles: normal, successful and error

Nguyen Duc Thinh 3 Aug 22, 2022
TDetailBoxView is a simple and flexible UI component fully written in Swift

TDetailBoxView is a simple and flexible UI component fully written in Swift. TDetailBoxView is developed to help users quickly display the detail screen without having to develop from scratch.

Nguyen Duc Thinh 2 Aug 18, 2022
TSwitchLabel is a simple and flexible UI component fully written in Swift.

TSwitchLabel is a simple and flexible UI component fully written in Swift. TSwitchLabel is developed for you to easily use when you need to design a UI with Label and Switch in the fastest way without having to spend time on develop from scratch.

Nguyen Duc Thinh 2 Aug 18, 2022
A Powerful , Extensible CSS Parser written in pure Swift.

A Powerful , Extensible CSS Parser written in pure Swift. Basic Usage From CSS: #View { "width" : 118; "height" : 120.5; "color1" : "#888888"; "co

null 273 Sep 9, 2022
MUDownloadButton - a Progressive Download button written in pure swift and inspired by AppStore download button

MUDownloadButton is a Progressive Download button written in pure swift and inspired by AppStore download button . feel free to contribute and pull requests

Mohammad ShahibZadeh 2 Feb 20, 2022
Swipe Left2Right & Right2Left, pure SwiftUI implementation

SwipeCell Preview Features Swipe cell from Left2Right & Right2Left. Destructive swipe Usage Simply add onSwipe(leading, trailing) method to your list

Enes Karaosman 266 Jan 6, 2023
☠️ An elegant way to show users that something is happening and also prepare them to which contents they are awaiting

Features • Guides • Installation • Usage • Miscellaneous • Contributing ?? README is available in other languages: ???? . ???? . ???? . ???? . ???? To

Juanpe Catalán 11.7k Jan 6, 2023
UIAdapter - An elegant solution to the iOS screen adaptation problem

UIAdapter - An elegant solution to the iOS screen adaptation problem ???? 天朝子民 Features Numerical type fast conversion Storyboard equal scale adaptati

LEE 39 Dec 25, 2022
Fully customizable Facebook reactions like control

Reactions is a fully customizable control to give people more ways to share their reaction in a quick and easy way. Requirements • Usage • Installatio

Yannick Loriot 585 Dec 28, 2022
FSPagerView is an elegant Screen Slide Library implemented primarily with UICollectionView.

FSPagerView is an elegant Screen Slide Library implemented primarily with UICollectionView. It is extremely helpful for making Banner、Product Show、Welcome/Guide Pages、Screen/ViewController Sliders.

Wenchao Ding 6.7k Jan 2, 2023
A simple and elegant UIKit for iOS.

HamsterUIKit A simple and elegant UIKit(Chart) for iOS, written in Swift. ?? Curve and bar Charts. ?? Protocols are designed based on UIKit(UITableVie

Howard Wang 30 Oct 2, 2022
Elegant Apply Style by Swift Method Chain.🌙

ApplyStyleKit ApplyStyleKit is a library that applies styles to UIKit using Swifty Method Chain. Normally, when applying styles to UIView etc.,it is n

shindyu 203 Nov 22, 2022
A paging scroll view for SwiftUI, using internal SwiftUI components

PagingView A paging scroll view for SwiftUI, using internal SwiftUI components. This is basically the same as TabView in the paging mode with the inde

Eric Lewis 18 Dec 25, 2022
SwiftUI-Margin adds a margin() viewModifier to a SwiftUI view.

SwiftUI-Margin adds a margin() viewModifier to a SwiftUI view. You will be able to layout the margins in a CSS/Flutter-like.

Masaaki Kakimoto(柿本匡章) 2 Jul 14, 2022
A way to quickly add a notification badge icon to any view. Make any view of a full-fledged animated notification center.

BadgeHub A way to quickly add a notification badge icon to any view. Demo/Example For demo: $ pod try BadgeHub To run the example project, clone the r

Jogendra 772 Dec 28, 2022