Search code examples
iosswiftuipagecontrol

Dynamically change the background color of the dots of UIPageControl.appearance


I have a UIPagevViewController which is used to show 4 ViewControllers. I want the dots background color to change based on the view's background color I am currently into. While I have managed to get the same background color for both the dots and the first page I fail to do so for every other one. In other words I want to dynamically change the dots background based on the view that is shown

           import UIKit

            class PageViewController: UIPageViewController,UIPageViewControllerDelegate, UIPageViewControllerDataSource {

            //my 4 viewControllers used in the UIPageViewController
            fileprivate lazy var pages : [UIViewController] = {
                return [
                    self.getViewController(withIdentifier: "firstViewControllerID"),
                    self.getViewController(withIdentifier: "secondViewControllerID"),
                    self.getViewController(withIdentifier: "thirdViewControllerID"),
                    self.getViewController(withIdentifier: "differentViewController")

                ]
            }()

         //function that accesses those view controllers used above from the storyboard
            fileprivate func getViewController(withIdentifier identifier: String) -> UIViewController
                {
                    return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: identifier)
                }
         /* needed function for the UIPageViewControllerDelegate, UIPageViewControllerDataSource protocols 
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
                  //Some Code. Unnecessary for the question
                }

            func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
                 {
                       //Some Code. Unnecessary for the question
                 }
          */
        //function where the dots colours are set
        private func setupPageControl() {
        let appearance = UIPageControl.appearance(whenContainedInInstancesOf: [UIPageViewController.self])
        appearance.pageIndicatorTintColor = UIColor.gray
        appearance.currentPageIndicatorTintColor = UIColor.red
        appearance.backgroundColor = pages[appearance.currentPage].view.backgroundColor
    }

    func presentationCount(for pageViewController: UIPageViewController) -> Int {
        setupPageControl()
        return pages.count
    }


    func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        return 0
    }




    override func viewDidLoad() {
        super.viewDidLoad()


       self.dataSource = self
       delegate = self
        if let firstVC = pages.first {
            setViewControllers([firstVC], direction: .forward, animated: true, completion: nil)
            setupPageControl()

        }
    }



}

enter image description here

enter image description here

First image->first page. Second image->second page. Look at the color of the dots background


Solution

  • Unfortunately you have no direct access to the page control built into a UIPageViewController. Therefore you have to use the appearance proxy in order to change its appearance (as you are already doing). But the appearance proxy only affects future instances of a thing; once the page control is already present, therefore, setting the appearance proxy will have no affect (as you have discovered).

    Therefore the simplest solution is to give up on the page control built into the UIPageViewController and just use your own UIPageControl whose dots you can change directly. You will have to coordinate it with the page view controller but that is not difficult.

    Another possibility is to try to get direct access to the UIPageViewController's UIPageControl. That's fragile because there is no official access, but that technique has been discussed here, as for example in this answer.