A fully customizable container view controller to display a set of ViewControllers in a horizontal scroll view. Written in Swift.

Overview

DTPagerController

Version License Platform

This is a control for iOS written in Swift. DTPagerController is simple to use and easy to customize.

Screenshots

Default segmented control

Custom segmented control

Usage

DTPagerController is extremely easy to use. In order to display two view controllers inside a pager controller. All you have to do is this many lines of code.

let viewController1 = ViewController()
let viewController2 = ViewController()
let pagerController = DTPagerController(viewControllers: [viewController1, viewController2])

Update page index

There are 3 different ways to update selected page index programmatically.

// Update selected page index with animation
pagerController.selectedPageIndex = 1

// Update selected page index with animation
pagerController.setSelectedPageIndex(1, animated: true)

// Update selected page index without animation
pagerController.setSelectedPageIndex(1, animated: false)

Custom UI

DTPagerController is also customizable in case you want to implement your own UI.

// Change the height of segmented control
pagerController.preferredSegmentedControlHeight = 60

// Change normal font of each segmented control
pagerController.font = UIFont.customFont(ofSize: 15)

// Change selected font of each segmented control
pagerController.selectedFont = UIFont.boldCustomFont(ofSize: 15)

// Change normal text color of each segmented control
pagerController.textColor = UIColor.black

// Change selected text color of each segmented control
pagerController.selectedTextColor = UIColor.red

// Change scroll indicator height
pagerController.perferredScrollIndicatorHeight = 3

Custom segmented control

From version 2.0.0, DTPagerController supports custom segmented control. Therefore, instead of using default DTSegmentedControl, you can provide your own segmented control or any 3rd-party segmented control libraries available out there. All you have to do is making your custom UIControl conform DTSegmentedControlProtocol. For example, as shown in sample project, HMSegmentedControl is made to conform DTSegmentedControlProtocol by using extension:

extension HMSegmentedControl: DTSegmentedControlProtocol {
    
    public func setImage(_ image: UIImage?, forSegmentAt segment: Int) {
        // Custom page control does not support
    }
    
    public func setTitle(_ title: String?, forSegmentAt segment: Int) {
        // Custom page control does not support
    }
    
    public func setTitleTextAttributes(_ attributes: [AnyHashable : Any]?, for state: UIControlState) {
        if state == UIControlState.normal {
            titleTextAttributes = attributes
        }
        else if state == UIControlState.selected {
            selectedTitleTextAttributes = attributes
        }
    }
    
}

Then we create new pager controller with the custom segmented control:

init(viewControllers controllers: [UIViewController]) {
        let segmentedControl = HMSegmentedControl(sectionTitles: ["Page 1", "Page 2", "Page 3"])
        super.init(viewControllers: controllers, pageSegmentedControl: segmentedControl!)
}

When using custom segmented control, it is recommneded to override/take a look at the following methods to customize behavior and appearance of each segments:

// Setup custom segmented control
func setUpSegmentedControl(viewControllers: [UIViewController])

// Update a custom appearance for segment
func updateAppearanceForSegmentedItem(at index: Int)

// Update a custom scroll indicator if exists
func updateScrollIndicator(with offsetRatio: CGFloat, scrollView: UIScrollView)

// Setup custom scroll indicator
func setUpScrollIndicator()

// Manually update segment title
func setTitle(_ title: String?, forSegmentAt segment: Int)
    
// Manually update segment image
func setImage(_ image: UIImage?, forSegmentAt segment: Int)

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

iOS 9.0+

Installation

CocoaPods

Simply add the following line to your Podfile:

For Swift 5:

pod 'DTPagerController'

For Swift 4.2:

pod 'DTPagerController', '~> 2.0.4'

Swift package manager

DTPagerController is available for SPM from version 3.0.2. Add the following to the dependencies of your Package.swift:

.package(url: "https://github.com/tungvoduc/DTPagerController", from: "version")

Author

Tung Vo, [email protected]

License

DTPagerController is available under the MIT license. See the LICENSE file for more info.

Feedbacks & requests

  • Open an issue if you find a bug, make a proposal or simply need some help.
  • You can also contact me via email.
Comments
  • Cannot find type 'UIViewController' in scope

    Cannot find type 'UIViewController' in scope

    I removed the old version from the pod and installed DTPagerController with SPM. The code is the same strangely , but after installing it with Swift Package Manager it does not compile.

    And of course it says it cannot find it in scope, maybe because UIViewController is UIKit after all ? ;)

    Here is the code giving problems:

    import Foundation
    
    public extension UIViewController {
        var pagerController: DTPagerController? {
            get {
                var viewController = parent
    
                while viewController != nil {
                    if let containerViewController = viewController as? DTPagerController {
                        return containerViewController
                    }
                    viewController = viewController?.parent
                }
    
                return nil
            }
        }
    }
    
    

    and the screenshot.

    Too bad I would really like to use SPM but it will have to wait I guess?

    Screenshot 2021-03-25 at 17 00 42

    opened by multitudes 9
  • First view incorrect height on load

    First view incorrect height on load

    When I initially load the view controller that contains my DTPagerController, the first view controller is always about half the height of the screen. As soon as I scroll to the next page, the height corrects itself. Interesting with the view (a tableview controller) does not update the height, only scrolling to a new page does. I've looked at through the code and I can't seem to find any work arounds. I've even tried to call crollViewDidScroll(pageScrollView) in my view did load to maybe try to trigger some code that updates the height, but it doesn't seem to help.

    opened by AaronLionsheep 9
  • bacgrkound Color, Bar Color

    bacgrkound Color, Bar Color

    These two arguments would be nice as a configuration when creating the PagerController()

    let pagerController = PagerController() pageController.bgColor = UIColor.grey pageController.scrollIndicatorColor = UIColor.red

    opened by alexookah 9
  • Disable/ Enable segments click

    Disable/ Enable segments click

    Hi , I want to disable the other segments click on first screen and enable it only after the button click on first screen. Could you please tell me how can I do this?

    opened by hemaks777 3
  • Orientation Rotating issues

    Orientation Rotating issues

    When rotating the device in landscape for examble. there seems some issues in auto laytout.

    check this video: https://streamable.com/f4h5o

    can this be resolved?

    opened by alexookah 3
  • Weird navigation controller's behaviour

    Weird navigation controller's behaviour

    Hello,

    I'm getting a weird bug in my application, and I'm getting the same problem in the Example provided in this library.

    Step to reproduce: 1 open the example app 2 fast switch between page "One" viewcontroller and "Two" viewcontroller for 4 or 5 time 3 tap on the "push" button

    As you can see the push doesn't perform because the navigation controller is nil.

    opened by CarioniStefano 2
  • There should be an option to show the segment if viewControllers.count = 1

    There should be an option to show the segment if viewControllers.count = 1

    Sometimes when having in most cases 2 or more Pages when the content is based dynamically on a server and some page fails you might have ended up in 1 viewController. I see in your code you simply hide the segment.

    i simply fixed this for me

    /// Height of segmented indicator /// Get only open var scrollIndicatorHeight: CGFloat { return viewControllers.count <= 1 ? perferredScrollIndicatorHeight : perferredScrollIndicatorHeight }

    /// Height of segmented control bar /// Get only open var segmentedControlHeight: CGFloat { return viewControllers.count <= 1 ? preferredSegmentedControlHeight : preferredSegmentedControlHeight }

    Maybe there should be an option to show the segment in case it fails to 1 viewController in order to show the title to the user to know which page is he currently on.

    What do you think?

    opened by alexookah 2
  • Fix: First view incorrect height on load

    Fix: First view incorrect height on load

    Hi. Fixed bug: #24

    How to fix?

    Deleted setup ViewController(setup size) code in didset method. Instead, add setup View Conrtoller(setup size) code in viewWillLayoutSubviews

    Has other update ?

    Yes.

    • Used early return.
    • Delete/fix white space.

    Please review and test! Thx φ('ᴗ'」)

    opened by ykeisuke 2
  • DTPagerControllerDelegate methods not firing in 2.0.4

    DTPagerControllerDelegate methods not firing in 2.0.4

    Pod version: ~> 2.0.4 (Swift 4.2)

    Tried console logging calls and debugging into all 3 methods:

    didChangeSelectedPageIndex
    willChangeSelectedPageIndex
    pageScrollViewDidScroll
    

    But none seem to be firing.

    Any ideas?

    opened by juliussss 1
  • don't change backgroundColor of segmentControl to clear

    don't change backgroundColor of segmentControl to clear

    I dowloaded sample project but i don't change backgroundColor of segmentControl to clear color. I have been set it to clear color but it is always display as if gray color

    opened by hien352911 1
  • PagerController disappear after pushViewController

    PagerController disappear after pushViewController

    Hello,

    I'm experiencing when I try to push a viewController from the DTPagerController.

    The push works, but when I get back from the "detail" view the controller doesn't show the pages. They are still there because if I swipe it work, but it's impossible to see the name of the page.

    See attached screenshot.

    Thanks,

    Carioni Stefano BEFORE Simulator Screen Shot - iPhone X - 2019-03-19 at 16 14 44 AFTER Simulator Screen Shot - iPhone X - 2019-03-19 at 16 14 50

    opened by CarioniStefano 1
  • How Can i Remove Divider Image from Segments

    How Can i Remove Divider Image from Segments

    There are Divider images in DTSegmentedControl that is causing problem of colour in not matching exact i want. I want to remove divider how can i remove or skip?

    opened by usman643 0
  • Facing Problem to implement Custom Segments

    Facing Problem to implement Custom Segments

    I'm doing the same code you have in example but in my project extension of HMSegmentedControl giving error to conform protocol selectedSegmentIndex but this is not implemented in your example code. how can i fix this?

    public var selectedSegmentIndex: Int {
            get {
                <#code#>
            }
            set(newValue) {
                <#code#>
            }
        }
    
    opened by usman643 0
  • PagerController Embedded with SearchBar at the top causing issues

    PagerController Embedded with SearchBar at the top causing issues

    For some reason when I try to add a searchBar at the top of the pager controller it comes looking all messed up. im not sure if it is not customizable to that extent or what but it usually ends up looking like this screen shot 2018-06-02 at 9 18 32 am

    Where the screen is black which makes zero sense because i set the background to white and it overlaps the searchbar.

    import UIKit
    import DTPagerController
    
    class NewSearchViewController: DTPagerController, UISearchBarDelegate {
        let dividerView = UIView()
    
        lazy var searchBar: UISearchBar = {
            let sb = UISearchBar()
            sb.placeholder = "Search"
            sb.searchBarStyle = .minimal
            sb.sizeToFit()
            sb.setScopeBarButtonTitleTextAttributes([ NSAttributedStringKey.foregroundColor.rawValue : UIColor.black], for: .normal)
            let textFieldInsideUISearchBar = sb.value(forKey: "searchField") as? UITextField
            textFieldInsideUISearchBar?.font = UIFont.systemFont(ofSize: 14)
            sb.layer.borderColor = UIColor.lightGray.cgColor
            sb.layer.borderWidth = 0.3
            sb.layer.cornerRadius = 5
            sb.layer.masksToBounds = true
            sb.showsCancelButton = true
            sb.barTintColor = UIColor.white
            sb.tintColor = UIColor.rgb(red: 24, green: 136, blue: 211)
            UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).backgroundColor = UIColor.rgb(red: 230, green: 230, blue: 230)
            sb.delegate = self
            return sb
        }()
        
        init() {
            super.init(viewControllers: [])
            title = "View Controller"
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            addVC()
            setupVC()
        }
        @objc func addVC(){
            let viewController1 = EventSearchCollectionView(collectionViewLayout:  UICollectionViewFlowLayout())
            let viewController2 = UserSearchCollectionView(collectionViewLayout:  UICollectionViewFlowLayout())
                    viewController1.title = "Events"
                    viewController2.title = "Users"
                    selectedFont =  UIFont(name: "Avenir-Medium", size: 14)!
                    selectedTextColor = UIColor.black
                    preferredSegmentedControlHeight = 40
                    perferredScrollIndicatorHeight = 1.8
                    scrollIndicator.backgroundColor = UIColor.black
                    viewControllers = [viewController1, viewController2]
        }
    
        @objc func setupVC(){
            view.addSubview(searchBar)
            view.addSubview(dividerView)
            searchBar.snp.makeConstraints { (make) in
                make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
                make.left.right.equalTo(view)
            }
            UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes([NSAttributedStringKey(rawValue: NSAttributedStringKey.foregroundColor.rawValue): UIColor.lightGray], for: .normal)
    
            dividerView.backgroundColor = .lightGray
            dividerView.snp.makeConstraints { (make) in
                make.left.right.equalTo(view)
                make.height.equalTo(0.5)
            }
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    }
    

    i have included the code above if that helps

    opened by Smiller193 1
Owner
Tung Vo
A passionate iOS developer.
Tung Vo
SwipeViewController is a Swift modification of RKSwipeBetweenViewControllers - navigate between pages / ViewControllers

SwipeViewController What is SwipeViewController? SwipeViewController enables you to modify the navigation bar and implement 'Swipe Buttons' that can u

Marek Fořt 657 Dec 6, 2022
A scroll pager that displays a list of tabs (segments) and manages paging between given views

ScrollPager A scroll pager similar to the one in Flipboard. The control creates a tabbar given a title or an image, and has the option of connecting t

Aryan Ghassemi 512 Aug 31, 2022
A custom tab bar controller for iOS written in Swift 4.2

A custom tab bar controller for iOS written in Swift 4.0 Screenshots Installation Cocoa Pods: pod 'AZTabBar' Swift Package Manager: You can use The Sw

Antonio Zaitoun 335 Dec 11, 2022
™️ A powerful paging view controller with interactive indicator bars

⭐️ Features Easy to implement page view controller with interactive indicator bars. Highly adaptable and powerful customization. Fully extensible with

UI At Six 2.5k Jan 2, 2023
AppKitFocusOverlay - Add hotkey(s) to display the key focus path for any window in your (running) AppKit application

AppKitFocusOverlay A simple package for displaying the current focus target path

Darren Ford 42 Dec 2, 2022
A fun, easy-to-use tab bar navigation controller for iOS.

CircleBar Don’t you, sometimes, miss fun user interfaces? Truth is, we do. Sure, you can't use them in enterprise apps for obvious reasons, but if you

softhaus 786 Dec 25, 2022
A custom tab bar controller for iOS.

ESTabBarController ESTabBarController is a custom tab bar controller for iOS. It has a tab indicator that moves animated along the bar when switching

null 122 Oct 6, 2022
Folding Tab Bar and Tab Bar Controller

FoldingTabBar.iOS Folding Tab Bar and Tab Bar Controller Inspired by this project on Dribbble Also, read how it was done in our blog Requirements iOS

Yalantis 3.7k Dec 21, 2022
ESTabBarController is a highly customizable TabBarController component, which is inherited from UITabBarController.

ESTabBarController is a highly customizable TabBarController component, which is inherited from UITabBarController. Why? In real-world developmen

Vincent Li 4.9k Jan 5, 2023
📱 TabBar – highly customizable tab bar for your SwiftUI application.

TabBar SwiftUI standard TabView component is not so flexible and to customize it you have to modify appearance proxy of UITabBar or implement your own

Tamerlan Satualdypov 162 Jan 5, 2023
TabDrawer is a customizable TabBar UI element that allows you to run a block of code upon TabBarItem selection

TabDrawer TabDrawer is a customizable TabBar UI element that allows you to run a block of code upon TabBarItem selection, or display a customizable dr

Winslow DiBona 503 Oct 5, 2022
Smooth customizable tabs for iOS apps.

SmoothTab Requirements iOS 11.0+ Swift 5.x Xcode 10+ Installation CocoaPods pod 'SmoothTab' How to use Complete screen To setup and customize the comp

Yervand Saribekyan, iOS Dev 105 Feb 13, 2022
Full Customizable Tabbar with IBInspectables

BEKCurveTabbar Full Customizable Tabbar with IBInspectables A fun replacement for UITabbar. The Component uses Bézier paths. Demo Example usage: You c

Behrad Kazemi 169 Dec 5, 2022
youtube iOS app template written in swift 5

Youtube iOS Template Youtube iOS Template is developed by Haik Aslanyan and written in Swift 3. Purpose of this repo is to show how ViewControllers ca

Henry Aslanyan 2.5k Jan 4, 2023
Animated top/bottom segmented control written in Swift.

Segmentio Animated top/bottom segmented control written in Swift. Check this project on dribbble. Requirements Xcode 10 iOS 8.x+ Swift 5.0 Installatio

Yalantis 2.4k Jan 9, 2023
🐛 WormTabStrip ViewPager for iOS written in Swift, which gives continuous feedback to the user when scrolling

Worm Tab Strip Worm Tab Strip is inspired by android SmartTabStrip, android view pager like library for iOS written in swift. Basically it was build u

EzimetYusup 176 Dec 13, 2022
Pager is the simplest and best way to implement sliding view controllers in Swift

Pager is the simplest and best way to implement sliding view controllers. Installation Drop in the Spring folder to your Xcode project. Or via CocoaPo

Lucas Oceano 234 Aug 5, 2022
A lightweight customized tabbar view. 📌

A lightweight customized tabbar view. Screenshots Features Installation Setup ToDos Credits Thanks License Screenshots Features Easily Configurable an

Hemang 137 Dec 16, 2022
:octocat: AdaptiveController is a 'Progressive Reduction' Swift UI module for adding custom states to Native or Custom iOS UI elements. Swift UI component by @Ramotion

ADAPTIVE TAB BAR 'Progressive Reduction' module for adding custom states to Native or Custom UI elements. We specialize in the designing and coding of

Ramotion 2k Nov 9, 2022