{"id":2801,"url":"https://github.com/xmartlabs/XLPagerTabStrip","last_synced_at":"2025-08-06T16:31:23.307Z","repository":{"id":24850933,"uuid":"28266028","full_name":"xmartlabs/XLPagerTabStrip","owner":"xmartlabs","description":"Android PagerTabStrip for iOS.","archived":false,"fork":false,"pushed_at":"2023-11-22T13:34:09.000Z","size":3983,"stargazers_count":6987,"open_issues_count":316,"forks_count":1328,"subscribers_count":128,"default_branch":"master","last_synced_at":"2024-12-06T19:02:12.993Z","etag":null,"topics":["carthage","cocoapods","ios-libraries","ios-ui","pager-controller","swift","swift-library"],"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/xmartlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","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},"funding":{"github":"xmartlabs","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2014-12-20T12:05:22.000Z","updated_at":"2024-12-02T02:23:50.000Z","dependencies_parsed_at":"2023-02-19T07:45:47.804Z","dependency_job_id":"67b39e7f-eea4-42d9-8e60-4582ab7daab7","html_url":"https://github.com/xmartlabs/XLPagerTabStrip","commit_stats":{"total_commits":223,"total_committers":55,"mean_commits":4.054545454545455,"dds":0.5156950672645739,"last_synced_commit":"211ed62aa376722cf93c429802a8b6ff66a8bd52"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2FXLPagerTabStrip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2FXLPagerTabStrip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2FXLPagerTabStrip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xmartlabs%2FXLPagerTabStrip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xmartlabs","download_url":"https://codeload.github.com/xmartlabs/XLPagerTabStrip/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228657278,"owners_count":17952700,"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":["carthage","cocoapods","ios-libraries","ios-ui","pager-controller","swift","swift-library"],"created_at":"2024-01-05T20:16:23.196Z","updated_at":"2024-12-09T16:31:03.462Z","avatar_url":"https://github.com/xmartlabs.png","language":"Swift","funding_links":["https://github.com/sponsors/xmartlabs"],"categories":["UI","Libs","Menu","Swift","UI [🔝](#readme)","Content"],"sub_categories":["Tab Bar","UI","Layout","Other free courses"],"readme":"![XLPagerTabStripView](https://raw.githubusercontent.com/xmartlabs/XLPagerTabStrip/master/XLPagerTabTrip.png)\n\n\u003cp align=\"left\"\u003e\n\u003ca href=\"https://travis-ci.org/xmartlabs/XLPagerTabStrip\"\u003e\u003cimg src=\"https://travis-ci.org/xmartlabs/XLPagerTabStrip.svg?branch=master\" alt=\"Build status\" /\u003e\u003c/a\u003e\n\u003cimg src=\"https://img.shields.io/badge/platform-iOS-blue.svg?style=flat\" alt=\"Platform iOS\" /\u003e\n\u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg src=\"https://img.shields.io/badge/swift5-compatible-4BC51D.svg?style=flat\" alt=\"Swift 5 compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\u003cimg src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://cocoapods.org/pods/XLPagerTabStrip\"\u003e\u003cimg src=\"https://img.shields.io/cocoapods/v/XLPagerTabStrip.svg\" alt=\"CocoaPods compatible\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://raw.githubusercontent.com/xmartlabs/XLPagerTabStrip/master/LICENSE\"\u003e\u003cimg src=\"http://img.shields.io/badge/license-MIT-blue.svg?style=flat\" alt=\"License: MIT\" /\u003e\n\u003c/a\u003e\n\u003c!-- \u003ca href=\"https://codebeat.co/projects/github-com-xmartlabs-xlpagertabstrip\"\u003e\u003cimg alt=\"codebeat badge\" src=\"https://codebeat.co/badges/f32c9ad3-0aa1-4b40-a632-9421211bd39e\" /\u003e\u003c/a\u003e --\u003e\n\n\u003c/p\u003e\n\nMade with ❤️ by [XMARTLABS](http://xmartlabs.com).\n\nAndroid [PagerTabStrip](http://developer.android.com/reference/android/support/v4/view/PagerTabStrip.html) for iOS!\n\n👉 Looking for a SwiftUI version? Check out [PagerTabStripView](https://github.com/xmartlabs/PagerTabStripView), it's fully written in pure SwiftUI. 👈\n\n**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.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\u003cimg src=\"Example/instagram.gif\" width=\"250\"/\u003e\u003c/th\u003e\n    \u003cth\u003e\u003cimg src=\"Example/spotify.gif\" width=\"250\"/\u003e\u003c/th\u003e\n    \u003cth\u003e\u003cimg src=\"Example/youtube.gif\" width=\"250\"/\u003e\u003c/th\u003e\n    \u003cth\u003e\u003cimg src=\"Example/pagerTabStripTypes.gif\" width=\"250\"/\u003e\u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Getting involved\n\n* If you **want to contribute** please feel free to **submit pull requests**.\n* If you **have a feature request** please **open an issue**.\n* If you **found a bug** or **need help** please **check older issues, [FAQ](#faq) and threads on [StackOverflow](http://stackoverflow.com/questions/tagged/XLPagerTabStrip) (Tag 'XLPagerTabStrip') before submitting an issue**.\n\n**Before contribute check the [CONTRIBUTING](CONTRIBUTING.md) file for more info.**\n\nIf you use **XLPagerTabStrip** in your app we would love to hear about it! Drop us a line on [twitter](https://twitter.com/xmartlabs).\n\n## Pager Types\n\nThe library provides 4 different ways to show the view controllers.\n\n### Button Bar\n\nThis is likely the most common pager type. It's used by many well-known apps such as instagram, youtube, skype, and many others.\n\n\u003cimg src=\"Example/barButton.gif\" width=\"250\"/\u003e\n\n### Bar\n\nThis mode doesn't show a title neither an image. It only shows a bar that indicates the current view controller.\n\n\u003cimg src=\"Example/bar.gif\" width=\"250\"/\u003e\n\n### Twitter\n\nA long time ago, the twitter app made use of this type of pager in the app main screen.\n\n\u003cimg src=\"Example/twitter.gif\" width=\"250\"/\u003e\n\n### Segmented\n\nThis mode uses a `UISegmentedControl` to indicate which view controller is being displayed.\n\n\u003cimg src=\"Example/segmented.gif\" width=\"250\"/\u003e\n\n## Usage\n\nBasically, 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.\n\nLet's see the steps to do this:\n\n##### Choose which type of pager we want to create\n\nFirst, 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`.\n\n\u003e All these built-in pager controllers extend from the base class `PagerTabStripViewController`.\n\u003e You can also make your custom pager controller by extending directly from `PagerTabStripViewController` in the event that no pager menu type fits your needs.\n\n```swift\nimport XLPagerTabStrip\n\nclass MyPagerTabStripName: ButtonBarPagerTabStripViewController {\n  ..\n}\n```\n\n##### Connect outlets and add layout constraints\n\nWe strongly recommend using IB to set up our page controller views.\n\nDrag a `UIViewController` into the storyboard and set up its class with your pager controller (`MyPagerTabStripName`).\nDrag a `UIScrollView` into your view controller view and connect `PagerTabStripViewController` `containerView` outlet with the scroll view.\n\nDepending on which type of paging view controller you are working with you may have to connect more outlets.\n\nFor `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.\n\n\u003e 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.\n\n##### Provide the view controllers that will appear embedded into the PagerTabStrip view controller\n\nYou can provide the view controllers by overriding `func viewControllers(for: pagerTabStripController: PagerTabStripViewController) -\u003e [UIViewController]` method.\n\n```swift\noverride public func viewControllers(for pagerTabStripController: PagerTabStripViewController) -\u003e [UIViewController] {\n  return [MyEmbeddedViewController(), MySecondEmbeddedViewController()]\n}\n```\n\n\u003e 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.\n\n\n##### Provide information to show in each indicator\n\nEvery UIViewController that will appear within the PagerTabStrip needs to provide either a title or an image.\nIn order to do so they should conform to `IndicatorInfoProvider` by implementing `func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -\u003e IndicatorInfo`\n which provides the information required to show the PagerTabStrip menu (indicator) associated with the view controller.\n\n```swift\nclass MyEmbeddedViewController: UITableViewController, IndicatorInfoProvider {\n\n  func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -\u003e IndicatorInfo {\n    return IndicatorInfo(title: \"My Child title\")\n  }\n}\n```\n\n**For a detailed step-by-step guide about how to use the library, please check out this community [blog post](https://medium.com/michaeladeyeri/how-to-implement-android-like-tab-layouts-in-ios-using-swift-3-578516c3aa9).**\n\nThat's it! We're done! 🍻🍻\n\n\n## Customization\n\n##### Pager Behaviour\n\nThe pager indicator can be updated progressive as we swipe or at once in the middle of the transition between the view controllers.\nBy setting up `pagerBehaviour` property we can choose how the indicator should be updated.\n\n```swift\npublic var pagerBehaviour: PagerTabStripBehaviour\n```\n\n```swift\npublic enum PagerTabStripBehaviour {\n    case common(skipIntermediteViewControllers: Bool)\n    case progressive(skipIntermediteViewControllers: Bool, elasticIndicatorLimit: Bool)\n}\n```\n\nDefault Values:\n```swift\n// Twitter Type\nPagerTabStripBehaviour.common(skipIntermediateViewControllers: true)\n// Segmented Type\nPagerTabStripBehaviour.common(skipIntermediateViewControllers: true)\n// Bar Type\nPagerTabStripBehaviour.progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true)\n// ButtonBar Type\nPagerTabStripBehaviour.progressive(skipIntermediateViewControllers: true, elasticIndicatorLimit: true)\n```\n\nAs you might have noticed, `common` and `progressive` enumeration cases have `skipIntermediateViewControllers` and `elasticIndicatorLimit` associated values.\n\n`skipIntermediateViewControllers` allows us to skip intermediate view controllers when a tab indicator is tapped.\n\n`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.\n\n##### PagerTabStripDelegate \u0026 PagerTabStripIsProgressiveDelegate\n\nNormally 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.\n\n```swift\npublic protocol PagerTabStripDelegate: class {\n\n    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int)\n}\n\npublic protocol PagerTabStripIsProgressiveDelegate : PagerTabStripDelegate {\n\n    func updateIndicator(for viewController: PagerTabStripViewController, fromIndex: Int, toIndex: Int, withProgressPercentage progressPercentage: CGFloat, indexWasChanged: Bool)\n}\n```\n\n\u003e Again, the method invoked by the library depends on the `pagerBehaviour` value.\n\n\n\n\n### ButtonBar Customization\n\n```swift\n\nsettings.style.buttonBarBackgroundColor: UIColor?\n// buttonBar minimumInteritemSpacing value, note that button bar extends from UICollectionView\nsettings.style.buttonBarMinimumInteritemSpacing: CGFloat?\n// buttonBar minimumLineSpacing value\nsettings.style.buttonBarMinimumLineSpacing: CGFloat?\n// buttonBar flow layout left content inset value\nsettings.style.buttonBarLeftContentInset: CGFloat?\n// buttonBar flow layout right content inset value\nsettings.style.buttonBarRightContentInset: CGFloat?\n\n// selected bar view is created programmatically so it's important to set up the following 2 properties properly\nsettings.style.selectedBarBackgroundColor = UIColor.black\nsettings.style.selectedBarHeight: CGFloat = 5\n\n// each buttonBar item is a UICollectionView cell of type ButtonBarViewCell\nsettings.style.buttonBarItemBackgroundColor: UIColor?\nsettings.style.buttonBarItemFont = UIFont.systemFont(ofSize: 18)\n// helps to determine the cell width, it represent the space before and after the title label\nsettings.style.buttonBarItemLeftRightMargin: CGFloat = 8\nsettings.style.buttonBarItemTitleColor: UIColor?\n// in case the barView items do not fill the screen width this property stretch the cells to fill the screen\nsettings.style.buttonBarItemsShouldFillAvailableWidth = true\n// only used if button bar is created programmatically and not using storyboards or nib files as recommended.\npublic var buttonBarHeight: CGFloat?\n```\n\n**Important:** Settings should be called before `viewDidLoad` is called.\n```swift\noverride func viewDidLoad() {\n   self.settings.style.selectedBarHeight = 2\n   self.settings.style.selectedBarBackgroundColor = UIColor.white\n\n   super.viewDidLoad()\n}\n```\n\n#####  Update cells when selected indicator changes\n\nWe 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`.\n\n```swift\npublic var changeCurrentIndex: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, animated: Bool) -\u003e Void)?\npublic var changeCurrentIndexProgressive: ((oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -\u003e Void)?\n```\n\nLet's see an example:\n\n```swift\nchangeCurrentIndexProgressive = { (oldCell: ButtonBarViewCell?, newCell: ButtonBarViewCell?, progressPercentage: CGFloat, changeCurrentIndex: Bool, animated: Bool) -\u003e Void in\n    guard changeCurrentIndex == true else { return }\n\n    oldCell?.label.textColor = UIColor(white: 1, alpha: 0.6)\n    newCell?.label.textColor = UIColor.white\n\n    if animated {\n        UIView.animate(withDuration: 0.1, animations: { () -\u003e Void in\n            newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)\n            oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)\n        })\n    }\n    else {\n        newCell?.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)\n        oldCell?.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)\n    }\n}\n```\n\n### Bar Type Customization\n\n```swift\nsettings.style.barBackgroundColor: UIColor?\nsettings.style.selectedBarBackgroundColor: UIColor?\n// barHeight is only set up when the bar is created programmatically and not using storyboards or xib files as recommended.\nsettings.style.barHeight: CGFloat = 5\n```\n\n### Twitter Type Customization\n\n```swift\nsettings.style.dotColor = UIColor(white: 1, alpha: 0.4)\nsettings.style.selectedDotColor = UIColor.white\nsettings.style.portraitTitleFont = UIFont.systemFont(ofSize: 18)\nsettings.style.landscapeTitleFont = UIFont.systemFont(ofSize: 15)\nsettings.style.titleColor = UIColor.white\n```\n\n### Segmented Type Customization\n\n```swift\nsettings.style.segmentedControlColor: UIColor?\n```\n\n\n\n## Requirements\n\n* iOS 9.3+\n* Xcode 10.2+\n\n## Examples\n\nFollow these 3 steps to run Example project: Clone XLPagerTabStrip repository, open XLPagerTabStrip workspace and run the *Example* project.\n\n## Installation\n\n### CocoaPods\n\n[CocoaPods](https://cocoapods.org/) is a dependency manager for Cocoa projects.\n\nTo install XLPagerTabStrip, simply add the following line to your Podfile:\n\n```ruby\npod 'XLPagerTabStrip', '~\u003e 9.0'\n```\n\n### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa.\n\nTo install XLPagerTabStrip, simply add the following line to your Cartfile:\n\n```ogdl\ngithub \"xmartlabs/XLPagerTabStrip\" ~\u003e 9.0\n```\n\n### SPM\n\n- File \u003e Swift Packages \u003e Add Package Dependency\n- Add `https://github.com/xmartlabs/XLPagerTabStrip.git`\n- Select \"Up to Next Major\" with \"9.0.0\"\n\n## FAQ\n\n#### How to change the visible child view controller programmatically\n\n`PagerTabStripViewController` provides the following methods to programmatically change the visible child view controller:\n\n```swift\nfunc moveToViewController(at index: Int)\nfunc moveToViewController(at index: Int, animated: Bool)\nfunc moveTo(viewController: UIViewController)\nfunc moveTo(viewController: UIViewController, animated: Bool)\n```\n\n\n#### How to migrate from Swift 2 to Swift 3 \u003ca name=\"migrate\"\u003e\u003c/a\u003e\n\nCheck out [our migration guide](https://github.com/xmartlabs/XLPagerTabStrip/blob/master/Migration.md)\n\n## Author\n\n* [Martin Barreto](https://github.com/mtnBarreto) ([@mtnBarreto](https://twitter.com/mtnBarreto))\n\n## Change Log\n\nThis can be found in the [CHANGELOG.md](CHANGELOG.md) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmartlabs%2FXLPagerTabStrip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxmartlabs%2FXLPagerTabStrip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmartlabs%2FXLPagerTabStrip/lists"}