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
A paging menu controller built from other view controllers placed inside a scroll view (like Spotify, Windows Phone, Instagram)

Unfortunately, life gets in the way sometimes and I won't be able to maintain this library any longer and upgrade this library to where it needs to be

null 5.2k Dec 31, 2022
A paging view controller with a highly customizable menu ✨

Getting Started | Customization | Installation Features Parchment lets you page between view controllers while showing any type of generic indicator t

Martin Rechsteiner 3k Jan 8, 2023
A fully customizable popup style menu for iOS 😎

Guide Check out the documentation and guides for details on how to use. (Available languages:) English 简体中文 What's a better way to know what PopMenu o

Cali Castle 1.5k Dec 30, 2022
The horizontal swiping navigation like on Facebook Messenger.

UIMenuScroll UIMenuScroll creating menu how on Facebook Messenger on take photo Installation CocoaPods is a dependency manager for Cocoa projects. You

Aleksey Pleshkov 18 Aug 9, 2022
slider view for choosing categories. add any UIView type as category item view. Fully customisable

CategorySliderView Horizontal or vertical slider view for choosing categories. Add any UIView type as category item view. Fully customisable Demo Inst

Cem Olcay 353 Nov 6, 2022
WWFortuneWheelView - A scroll wheel that can be customized.

WWFortuneWheelView A scroll wheel that can be customized. 一個可以自訂數量的滾輪. Installation with Swift Package Manager dependencies: [ .package(url: "http

William-Weng 1 Jan 6, 2022
The elegant yet functional dropdown menu, written in Swift, appears underneath the navigation bar to display a list of defined items when a user clicks on the navigation title.

Introduction The elegant yet functional dropdown menu, written in Swift, appears underneath the navigation bar to display a list of defined items when

Tho Pham 2.7k Dec 28, 2022
A side menu controller written in Swift for iOS

Description SideMenuController is a custom container view controller written in Swift which will display the main content within a center panel and th

Teo 1.2k Dec 29, 2022
Menu controller with expandable item groups, custom position and appearance animation written with Swift. Similar to ActionSheet style of UIAlertController.

Easy to implement controller with expanding menu items. Design is very similar to iOS native ActionSheet presentation style of a UIAlertController. As

Anatoliy Voropay 22 Dec 27, 2022
iOS Slide Menu Controller. It is written in pure swift.

SlideMenuController Requirements iOS 9+ Installation SlideMenuController is available through CocoaPods. To install it, simply add the following line

Myung gi son 40 Jan 16, 2022
Interactive view transition to display menus with flowing and bouncing effects in Swift

FlowingMenu FlowingMenu provides an interactive transition manager to display menu with a flowing and bouncing effects. The Objective-C countepart is

Yannick Loriot 975 Dec 21, 2022
Drawer view controller that easy to use!

KWDrawerController Drawer view controller that is easy to use! Installation CocoaPods (iOS 8+ projects) KWDrawerController is available on CocoaPods.

Jungwon An 157 Jun 14, 2022
SwiftySideMenu is a lightweight and easy to use side menu controller to add left menu and center view controllers with scale animation based on Pop framework.

SwiftySideMenu SwiftySideMenu is a lightweight, fully customizable, and easy to use controller to add left menu and center view controllers with scale

Hossam Ghareeb 84 Feb 4, 2022
Drawer view controller that easy to use!

KWDrawerController Drawer view controller that is easy to use! Installation CocoaPods (iOS 8+ projects) KWDrawerController is available on CocoaPods.

Jungwon An 157 Jun 14, 2022
A simple customizable side menu written in SwiftUI.

NSideMenu Description A simple customizable side menu written in SwiftUI. Give a Star! ⭐ Feel free to request an issue on github if you find bugs or r

null 5 Oct 10, 2022
Control your display's brightness from the macOS menu bar. Simple and easy to use.

MonitorControl Lite Control your display's brightness from the macOS menu bar. Simple and easy to use. About MonitorControl Lite is a simplified versi

null 62 Dec 11, 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
Custom transition between controllers. Settings controller for your iOS app.

SPLarkController About Transition between controllers to top. You can change animatable height after presentation controller. For presentation and dis

Ivan Vorobei 965 Dec 17, 2022
Customizable progress indicator library in Swift

Gradient Circular Progress Customizable progress indicator library in Swift Requirements Swift 5.1 iOS 8.0 or later Screen Shots Preset style: BlueDar

keygx 523 Dec 5, 2022