Convert Figma logo to code with AI

xmartlabs logoXLPagerTabStrip

Android PagerTabStrip for iOS.

6,973
1,325
6,973
317

Top Related Projects

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

A highly customizable drop-in replacement for UISegmentedControl.

2,836

™️ A powerful paging view controller with interactive indicator bars

Animated top/bottom segmented control written in Swift.

:octocat: 📃 FoldingCell is an expanding content cell with animation made by @Ramotion

Quick Overview

XLPagerTabStrip is an iOS library for creating a pager tab strip controller with interactive pager views. It provides a customizable interface for switching between different view controllers using a tab strip at the top of the screen, similar to the UI seen in many popular iOS applications.

Pros

  • Highly customizable with various styles and options
  • Smooth animations and transitions between tabs
  • Supports both Swift and Objective-C
  • Easy integration with existing iOS projects

Cons

  • Limited to iOS platform only
  • May require additional setup for complex layouts
  • Documentation could be more comprehensive
  • Some reported issues with Swift Package Manager integration

Code Examples

  1. Creating a basic ButtonBarPagerTabStripViewController:
import XLPagerTabStrip

class MyPagerTabStripViewController: ButtonBarPagerTabStripViewController {
    override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
        return [
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "FirstViewController"),
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController"),
            UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ThirdViewController")
        ]
    }
}
  1. Customizing the appearance of the ButtonBar:
override func viewDidLoad() {
    settings.style.buttonBarBackgroundColor = .black
    settings.style.buttonBarItemBackgroundColor = .black
    settings.style.selectedBarBackgroundColor = .white
    settings.style.buttonBarItemFont = .boldSystemFont(ofSize: 14)
    settings.style.selectedBarHeight = 2.0
    settings.style.buttonBarMinimumLineSpacing = 0
    settings.style.buttonBarItemTitleColor = .white
    settings.style.buttonBarItemsShouldFillAvailableWidth = true
    settings.style.buttonBarLeftContentInset = 0
    settings.style.buttonBarRightContentInset = 0

    super.viewDidLoad()
}
  1. Implementing a custom indicator:
class MyCustomIndicator: PagerTabStripIndicator {
    private let indicatorHeight: CGFloat = 4.0
    private let indicatorView = UIView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(indicatorView)
        indicatorView.backgroundColor = .red
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        indicatorView.frame = CGRect(x: 0, y: bounds.height - indicatorHeight, width: bounds.width, height: indicatorHeight)
    }
}

Getting Started

  1. Install XLPagerTabStrip using CocoaPods by adding the following to your Podfile:

    pod 'XLPagerTabStrip', '~> 9.0'
    
  2. Run pod install in your project directory.

  3. Import XLPagerTabStrip in your Swift file:

    import XLPagerTabStrip
    
  4. Create a new view controller that subclasses ButtonBarPagerTabStripViewController and implement the viewControllers(for:) method to return an array of view controllers for your tabs.

  5. Customize the appearance and behavior of your pager tab strip as needed using the settings property.

Competitor Comparisons

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

Pros of FSPagerView

  • More lightweight and focused specifically on paging views
  • Supports infinite scrolling out of the box
  • Easier to customize individual page appearances

Cons of FSPagerView

  • Less comprehensive than XLPagerTabStrip, which offers more features
  • Limited to horizontal scrolling, while XLPagerTabStrip supports both horizontal and vertical
  • Lacks built-in support for custom tab designs

Code Comparison

FSPagerView:

let pagerView = FSPagerView(frame: frame)
pagerView.register(FSPagerViewCell.self, forCellWithReuseIdentifier: "cell")
pagerView.itemSize = CGSize(width: 200, height: 300)
pagerView.dataSource = self
pagerView.delegate = self

XLPagerTabStrip:

let pagerController = ButtonBarPagerTabStripViewController()
pagerController.settings.style.buttonBarBackgroundColor = .white
pagerController.settings.style.buttonBarItemBackgroundColor = .white
pagerController.settings.style.selectedBarBackgroundColor = .black
pagerController.settings.style.buttonBarItemFont = .boldSystemFont(ofSize: 14)

FSPagerView is more straightforward to set up for basic paging functionality, while XLPagerTabStrip offers more extensive customization options for tab appearance and behavior. XLPagerTabStrip provides a higher-level abstraction with its view controller-based approach, whereas FSPagerView focuses on the view layer, giving developers more direct control over the paging component.

A highly customizable drop-in replacement for UISegmentedControl.

Pros of HMSegmentedControl

  • Lightweight and focused on segmented control functionality
  • Easy to customize appearance with various style options
  • Supports both text and images for segment content

Cons of HMSegmentedControl

  • Limited to segmented control functionality, lacking pager features
  • Less actively maintained compared to XLPagerTabStrip
  • Fewer built-in animations and transitions

Code Comparison

HMSegmentedControl:

let segmentedControl = HMSegmentedControl(sectionTitles: ["One", "Two", "Three"])
segmentedControl.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 40)
segmentedControl.addTarget(self, action: #selector(segmentedControlChangedValue(_:)), for: .valueChanged)
view.addSubview(segmentedControl)

XLPagerTabStrip:

class MyPagerViewController: ButtonBarPagerTabStripViewController {
    override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
        return [UIViewController(), UIViewController(), UIViewController()]
    }
}

XLPagerTabStrip offers a more comprehensive solution for creating tabbed interfaces with paging functionality, while HMSegmentedControl focuses solely on providing a customizable segmented control. XLPagerTabStrip is better suited for complex tab-based navigation, whereas HMSegmentedControl is ideal for simpler segmented control needs within a single view.

2,836

™️ A powerful paging view controller with interactive indicator bars

Pros of Tabman

  • More customizable and flexible UI options
  • Better support for Swift and SwiftUI
  • Actively maintained with frequent updates

Cons of Tabman

  • Steeper learning curve due to more complex API
  • Larger codebase and potentially higher memory footprint
  • May require more setup code for basic implementations

Code Comparison

XLPagerTabStrip:

let pagerController = ButtonBarPagerTabStripViewController()
pagerController.dataSource = self
pagerController.delegate = self

Tabman:

let tabViewController = TabmanViewController()
tabViewController.dataSource = self
tabViewController.delegate = self
tabViewController.bar.style = .buttonBar()
tabViewController.addBar(at: .top, dataSource: .view(TabmanBarView()))

Summary

Tabman offers more customization options and better Swift support, but may require more setup and have a steeper learning curve. XLPagerTabStrip is simpler to implement for basic use cases but may lack some advanced features. Both libraries provide similar core functionality for creating tab-based interfaces in iOS apps.

Animated top/bottom segmented control written in Swift.

Pros of Segmentio

  • More customizable appearance with built-in styles and animations
  • Supports both text and image-based segments
  • Lightweight and easy to integrate

Cons of Segmentio

  • Limited to segmented control functionality
  • Less comprehensive documentation compared to XLPagerTabStrip
  • Fewer configuration options for complex layouts

Code Comparison

XLPagerTabStrip:

let barButton = ButtonBarView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 50))
barButton.selectedBar.backgroundColor = .orange
barButton.backgroundColor = .black

Segmentio:

let segmentioView = Segmentio(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 50))
segmentioView.setup(
    content: [SegmentioItem(title: "First", image: nil)],
    style: .onlyLabel,
    options: SegmentioOptions()
)

XLPagerTabStrip offers a more comprehensive solution for creating paged interfaces with customizable tab strips, while Segmentio focuses on providing a highly customizable segmented control. XLPagerTabStrip is better suited for complex view controller management, whereas Segmentio excels in creating visually appealing segmented controls with various styles and animations. The choice between the two depends on the specific requirements of your project and the level of customization needed for the user interface.

:octocat: 📃 FoldingCell is an expanding content cell with animation made by @Ramotion

Pros of folding-cell

  • Unique and visually appealing animation for expanding/collapsing cells
  • Customizable design with easy-to-use interface
  • Lightweight library focused on a single, specific UI component

Cons of folding-cell

  • Limited to table view cells, less versatile than a full tab/paging solution
  • May require more custom implementation for complex use cases
  • Potentially less suitable for apps requiring multiple navigation patterns

Code Comparison

folding-cell:

let cell = FoldingCell()
cell.itemCount = 4
cell.delegate = self
tableView.register(FoldingCell.self, forCellReuseIdentifier: "cell")

XLPagerTabStrip:

class MyPagerViewController: ButtonBarPagerTabStripViewController {
    override func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
        return [UIViewController(), UIViewController(), UIViewController()]
    }
}

Summary

folding-cell offers a unique and visually appealing animation for expanding and collapsing table view cells, making it ideal for apps that want to showcase content in an interactive way. However, it's more limited in scope compared to XLPagerTabStrip, which provides a full paging and tab strip solution for navigation between multiple view controllers. XLPagerTabStrip is more versatile and suitable for apps requiring complex navigation patterns, while folding-cell excels in creating engaging list-based interfaces with expandable content.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

XLPagerTabStripView

Build status Platform iOS Swift 5 compatible Carthage compatible CocoaPods compatible License: MIT

Made with ❤️ by XMARTLABS.

Android PagerTabStrip for iOS!

👉 Looking for a SwiftUI version? Check out PagerTabStripView, it's fully written in pure SwiftUI. 👈

XLPagerTabStrip is a Container View Controller that allows us to switch easily among a collection of view controllers. Pan gesture can be used to move on to next or previous view controller. It shows a interactive indicator of the current, previous, next child view controllers.

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, FAQ and threads on StackOverflow (Tag 'XLPagerTabStrip') before submitting an issue.

Before contribute check the CONTRIBUTING file for more info.

If you use XLPagerTabStrip in your app we would love to hear about it! Drop us a line on twitter.

Pager Types

The library provides 4 different ways to show the view controllers.

Button Bar

This is likely the most common pager type. It's used by many well-known apps such as instagram, youtube, skype, and many others.

Bar

This mode doesn't show a title neither an image. It only shows a bar that indicates the current view controller.

Twitter

A long time ago, the twitter app made use of this type of pager in the app main screen.

Segmented

This mode uses a UISegmentedControl to indicate which view controller is being displayed.

Usage

Basically, we just need to provide the list of child view controllers to show, and these view controllers should provide the information (title or image) that will be shown in the associated indicator.

Let's see the steps to do this:

Choose which type of pager we want to create

First, we must choose the type of pager we want to create. Depending on our choice, we will have to create a view controller that extends from one of the following controllers: TwitterPagerTabStripViewController, ButtonBarPagerTabStripViewController, SegmentedPagerTabStripViewController, BarPagerTabStripViewController.

All these built-in pager controllers extend from the base class PagerTabStripViewController. You can also make your custom pager controller by extending directly from PagerTabStripViewController in the event that no pager menu type fits your needs.

import XLPagerTabStrip

class MyPagerTabStripName: ButtonBarPagerTabStripViewController {
  ..
}
Connect outlets and add layout constraints

We strongly recommend using IB to set up our page controller views.

Drag a UIViewController into the storyboard and set up its class with your pager controller (MyPagerTabStripName). Drag a UIScrollView into your view controller view and connect PagerTabStripViewController containerView outlet with the scroll view.

Depending on which type of paging view controller you are working with you may have to connect more outlets.

For BarPagerTabStripViewController, we should connect barView outlet. barView type is UIView. ButtonBarPagerTabStripViewController requires us to connect buttonBarView outlet. buttonBarView type is ButtonBarView which extends from UICollectionView. SegmentedPagerTabStripViewController has a segmentedControl outlet; if the outlet is not connected the library try to set up the navigationItem titleView property using a UISegmentedControl. TwitterPagerTabStripViewController doesn't require us to connect any additional outlet.

The example project contains a example for each pager controller type and we can look into it to see how views were added and how outlets were connected.

Provide the view controllers that will appear embedded into the PagerTabStrip view controller

You can provide the view controllers by overriding func viewControllers(for: pagerTabStripController: PagerTabStripViewController) -> [UIViewController] method.

override public func viewControllers(for pagerTabStripController: PagerTabStripViewController) -> [UIViewController] {
  return [MyEmbeddedViewController(), MySecondEmbeddedViewController()]
}

The method above is the only method declared in PagerTabStripDataSource protocol. We don't need to explicitly conform to it since base pager class already does it.

Provide information to show in each indicator

Every UIViewController that will appear within the PagerTabStrip needs to provide either a title or an image. In order to do so they should conform to IndicatorInfoProvider by implementing func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo which provides the information required to show the PagerTabStrip menu (indicator) associated with the view controller.

class MyEmbeddedViewController: UITableViewController, IndicatorInfoProvider {

  func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
    return IndicatorInfo(title: "My Child title")
  }
}

For a detailed step-by-step guide about how to use the library, please check out this community blog post.

That's it! We're done! 🍻🍻

Customization

Pager Behaviour

The pager indicator can be updated progressive as we swipe or at once in the middle of the transition between the view controllers. By setting up pagerBehaviour property we can choose how the indicator should be updated.

public var pagerBehaviour: PagerTabStripBehaviour
public enum PagerTabStripBehaviour {
    case common(skipIntermediteViewControllers: Bool)
    case progressive(skipIntermediteViewControllers: Bool, elasticIndicatorLimit: Bool)
}

Default Values:

// Twitter Type
PagerTabStripBehaviour.common(skipIntermediateViewControllers: true)
// Segmented Type
PagerTabStripBehaviour.common(skipIntermediateViewControllers: true)
// Bar Type
PagerTabStripBehaviour.progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true)
// ButtonBar Type
PagerTabStripBehaviour.progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true)

As you might have noticed, common and progressive enumeration cases have skipIntermediateViewControllers and elasticIndicatorLimit associated values.

skipIntermediateViewControllers allows us to skip intermediate view controllers when a tab indicator is tapped.

elasticIndicatorLimit allows us to tension the indicator when we reach a limit, I mean when we try to move forward from last indicator or move back from first indicator.

PagerTabStripDelegate & PagerTabStripIsProgressiveDelegate

Normally we don't need to implement these protocols because each pager type already conforms to it in order to properly update its indicator. However, there may be some scenarios when overriding a method may come in handy.

public protocol PagerTabStripDelegate: class {

    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int)
}

public protocol PagerTabStripIsProgressiveDelegate : PagerTabStripDelegate {

    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool)
}

Again, the method invoked by the library depends on the pagerBehaviour value.

ButtonBar Customization


settings.style.buttonBarBackgroundColor: UIColor?
// buttonBar minimumInteritemSpacing value, note that button bar extends from UICollectionView
settings.style.buttonBarMinimumInteritemSpacing: CGFloat?
// buttonBar minimumLineSpacing value
settings.style.buttonBarMinimumLineSpacing: CGFloat?
// buttonBar flow layout left content inset value
settings.style.buttonBarLeftContentInset: CGFloat?
// buttonBar flow layout right content inset value
settings.style.buttonBarRightContentInset: CGFloat?

// selected bar view is created programmatically so it's important to set up the following 2 properties properly
settings.style.selectedBarBackgroundColor = UIColor.black
settings.style.selectedBarHeight: CGFloat = 5

// each buttonBar item is a UICollectionView cell of type ButtonBarViewCell
settings.style.buttonBarItemBackgroundColor: UIColor?
settings.style.buttonBarItemFont = UIFont.systemFont(ofSize: 18)
// helps to determine the cell width, it represent the space before and after the title label
settings.style.buttonBarItemLeftRightMargin: CGFloat = 8
settings.style.buttonBarItemTitleColor: UIColor?
// in case the barView items do not fill the screen width this property stretch the cells to fill the screen
settings.style.buttonBarItemsShouldFillAvailableWidth = true
// only used if button bar is created programmatically and not using storyboards or nib files as recommended.
public var buttonBarHeight: CGFloat?

Important: Settings should be called before viewDidLoad is called.

override func viewDidLoad() {
   self.settings.style.selectedBarHeight = 2
   self.settings.style.selectedBarBackgroundColor = UIColor.white

   super.viewDidLoad()
}
Update cells when selected indicator changes

We may need to update the indicator cell when the displayed view controller changes. The following function properties help to accomplish that. Depending on our pager pagerBehaviour value we will have to set up changeCurrentIndex or changeCurrentIndexProgressive.

public var changeCurrentIndex: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, animated: Bool) -> Void)?
public var changeCurrentIndexProgressive: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void)?

Let's see an example:

changeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -> Void in
    guard changeCurrentIndex == true else { return }

    oldCell?.label.textColor = UIColor(white: 1, alpha: 0.6)
    newCell?.label.textColor = UIColor.white

    if animated {
        UIView.animate(withDuration: 0.1, animations: { () -> Void in
            newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
        })
    }
    else {
        newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
        oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
    }
}

Bar Type Customization

settings.style.barBackgroundColor: UIColor?
settings.style.selectedBarBackgroundColor: UIColor?
// barHeight is only set up when the bar is created programmatically and not using storyboards or xib files as recommended.
settings.style.barHeight: CGFloat = 5

Twitter Type Customization

settings.style.dotColor = UIColor(white: 1, alpha: 0.4)
settings.style.selectedDotColor = UIColor.white
settings.style.portraitTitleFont = UIFont.systemFont(ofSize: 18)
settings.style.landscapeTitleFont = UIFont.systemFont(ofSize: 15)
settings.style.titleColor = UIColor.white

Segmented Type Customization

settings.style.segmentedControlColor: UIColor?

Requirements

  • iOS 9.3+
  • Xcode 10.2+

Examples

Follow these 3 steps to run Example project: Clone XLPagerTabStrip repository, open XLPagerTabStrip workspace and run the Example project.

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

To install XLPagerTabStrip, simply add the following line to your Podfile:

pod 'XLPagerTabStrip', '~> 9.0'

Carthage

Carthage is a simple, decentralized dependency manager for Cocoa.

To install XLPagerTabStrip, simply add the following line to your Cartfile:

github "xmartlabs/XLPagerTabStrip" ~> 9.0

SPM

  • File > Swift Packages > Add Package Dependency
  • Add https://github.com/xmartlabs/XLPagerTabStrip.git
  • Select "Up to Next Major" with "9.0.0"

FAQ

How to change the visible child view controller programmatically

PagerTabStripViewController provides the following methods to programmatically change the visible child view controller:

func moveToViewController(at index: Int)
func moveToViewController(at index: Int, animated: Bool)
func moveTo(viewController: UIViewController)
func moveTo(viewController: UIViewController, animated: Bool)

How to migrate from Swift 2 to Swift 3

Check out our migration guide

Author

Change Log

This can be found in the CHANGELOG.md file.