Skip to content

UIPageControl

Overview

UIPageControl is a UIKit control in iOS that provides a visual indicator for navigating through a series of pages or content items. It displays a sequence of dots, where each dot represents a page, and the highlighted dot indicates the currently active page. Commonly used with UIScrollView or other paging interfaces, it allows users to visualize and navigate between pages.

Key Features

  • Displays a series of dots to represent pages.
  • Highlights the current page with a distinct dot.
  • Supports user interaction to switch between pages.
  • Customizable appearance, including dot colors and sizes.
  • Lightweight and easy to integrate with paging interfaces like UIScrollView.

Usage

UIPageControl is typically used in scenarios where content is divided into multiple pages, such as onboarding screens, image carousels, or tutorials. It can be configured programmatically or via Interface Builder in Xcode.

Basic Setup

To use UIPageControl, add it to your view hierarchy and configure its properties, such as the number of pages and the current page.

Example: Creating a UIPageControl Programmatically

swift
import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Create UIPageControl
        let pageControl = UIPageControl()
        pageControl.frame = CGRect(x: 50, y: 500, width: 200, height: 20)
        pageControl.numberOfPages = 5 // Set total number of pages
        pageControl.currentPage = 0   // Set starting page
        pageControl.addTarget(self, action: #selector(pageControlTapped(_:)), for: .valueChanged)
        
        // Add to view
        view.addSubview(pageControl)
    }
    
    @objc func pageControlTapped(_ sender: UIPageControl) {
        // Handle page change
        print("Current page: \(sender.currentPage)")
    }
}

Integration with UIScrollView

UIPageControl is often paired with a UIScrollView to create a paging interface. The scroll view handles the content, while the page control provides the visual indicator.

Example: UIPageControl with UIScrollView

swift
import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {
    let scrollView = UIScrollView()
    let pageControl = UIPageControl()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup ScrollView
        scrollView.frame = view.bounds
        scrollView.isPagingEnabled = true
        scrollView.delegate = self
        scrollView.contentSize = CGSize(width: view.frame.width * 3, height: view.frame.height)
        
        // Setup PageControl
        pageControl.frame = CGRect(x: 50, y: view.frame.height - 50, width: 200, height: 20)
        pageControl.numberOfPages = 3
        pageControl.currentPage = 0
        pageControl.addTarget(self, action: #selector(pageControlTapped(_:)), for: .valueChanged)
        
        // Add to view
        view.addSubview(scrollView)
        view.addSubview(pageControl)
        
        // Add sample content to scrollView
        for i in 0..<3 {
            let page = UIView(frame: CGRect(x: view.frame.width * CGFloat(i), y: 0, width: view.frame.width, height: view.frame.height))
            page.backgroundColor = [UIColor.red, UIColor.blue, UIColor.green][i]
            scrollView.addSubview(page)
        }
    }
    
    @objc func pageControlTapped(_ sender: UIPageControl) {
        // Scroll to selected page
        let page = sender.currentPage
        let offset = CGPoint(x: scrollView.frame.width * CGFloat(page), y: 0)
        scrollView.setContentOffset(offset, animated: true)
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // Update page control based on scroll position
        let pageIndex = round(scrollView.contentOffset.x / scrollView.frame.width)
        pageControl.currentPage = Int(pageIndex)
    }
}

Key Properties

  • numberOfPages: Sets the total number of pages (dots) to display.
  • currentPage: Specifies the currently active page (zero-based index).
  • pageIndicatorTintColor: Sets the color of inactive page dots.
  • currentPageIndicatorTintColor: Sets the color of the active page dot.
  • hidesForSinglePage: If true, hides the control when there is only one page.
  • defersCurrentPageDisplay: If true, delays updating the current page until updateCurrentPageDisplay() is called.

Customization

You can customize the appearance of UIPageControl to match your app’s design:

Changing Dot Colors

swift
pageControl.pageIndicatorTintColor = UIColor.gray
pageControl.currentPageIndicatorTintColor = UIColor.blue

Hiding for Single Page

swift
pageControl.hidesForSinglePage = true

Custom Dot Images (iOS 14+)

In iOS 14 and later, you can use custom images for page indicators:

swift
pageControl.setIndicatorImage(UIImage(named: "customDot"), forPage: 0)

Accessibility

UIPageControl supports accessibility by default, but you can enhance it:

  • Set isAccessibilityElement = true to ensure VoiceOver recognizes it.
  • Provide an accessibilityLabel to describe the control’s purpose, e.g., "Page indicator for onboarding screens".
  • Use accessibilityValue to describe the current page, e.g., "Page 1 of 5".
swift
pageControl.isAccessibilityElement = true
pageControl.accessibilityLabel = "Page indicator"
pageControl.accessibilityValue = "Page \(pageControl.currentPage + 1) of \(pageControl.numberOfPages)"

Limitations

  • UIPageControl only provides the visual indicator and user interaction; it does not handle content scrolling or paging logic.
  • Limited customization for dot size and spacing (some advanced customizations require a custom implementation).
  • Custom images for indicators are only available in iOS 14 and later.

Best Practices

  • Pair with UIScrollView or similar for seamless paging experiences.
  • Update currentPage when the user scrolls to keep the control in sync.
  • Use distinct colors for active and inactive dots to improve visibility.
  • Ensure accessibility support for inclusive user experiences.
  • Test on various screen sizes to ensure proper placement and visibility.

Availability

  • Available in iOS 2.0 and later.
  • Compatible with UIKit-based apps (not SwiftUI, though SwiftUI has its own PageControl equivalent).

References

Released under the MIT License.