Custom color and size for UIPageControl dots?

I know this question is a common one. But I have not found a working solution in Swift, only vague (to me) instructions. Here's one example question: https://forums.developer.apple.com/message/73732. There are many more at StackOverflow and elsewhere. I've even found instructions on how to rotate the dot display to vertical.


The default dots are nice but too small, in my opinion, for a tutorial. The user may miss them and not realize how to proceed. I want mine to be bigger, maybe twice as big, and I'd like control over the dot colors while I'm at it.


I have a single UIPageViewController with a single view controller under it's control, see below. It works beautifully, except for the small size of the dots. Each tutorial page gets an image and a text block.


If I add a UIPageControl to the subservient view controller containing the image and text views, I can control the size and the dot colors. But the default controller still shows and is not affected. How can I seize control of the default dots, or hide them so I can replace them with my own? I should add that I don't need to change the relative spacing between the dots, I just want the whole thing larger. "pageControl.transform = CGAffineTransform(scaleX: 2, y: 2)" works fine on my custom UIPageControl.


import UIKit
class ManagePageViewController: UIPageViewController {
  var photos = ["photo1", "photo2", "photo3", "photo4", "photo5"]
  var currentIndex: Int!
  var textFields = ["pageText1", "pageText2", "pageText3", "pageText4", "pageText5"]


 override func viewDidLoad() {
    super.viewDidLoad()
    dataSource = self
    if let viewController = tutorialController(currentIndex ?? 0) {
      let viewControllers = [viewController]
      setViewControllers(viewControllers,
                         direction: .forward,
                         animated: false,
                         completion: nil)
    }
  }

func tutorialController(_ index: Int) -> myTutorialViewController? {
 if let storyboard = storyboard,
      let page = storyboard.instantiateViewController(withIdentifier: "myTutorialViewController") as? myTutorialViewController {
      page.photoName = photos[index]
      page.photoIndex = index
      page.textName = textFields[index]
      page.textIndex = index
      return page
    }
    return nil
  }
}


extension ManagePageViewController: UIPageViewControllerDataSource {


  func pageViewController(_ pageViewController: UIPageViewController,
                          viewControllerBefore viewController: UIViewController) -> UIViewController? {

    if let viewController = viewController as? PhotoCommentViewController,
      let index = viewController.photoIndex,
      index > 0 {
      return viewPhotoCommentController(index - 1)
    }
    return nil
  }

  func pageViewController(_ pageViewController: UIPageViewController,
                          viewControllerAfter viewController: UIViewController) -> UIViewController? {

    if let viewController = viewController as? myTutorialViewController,
      let index = viewController.photoIndex,
      (index + 1) < photos.count {
      return tutorialController(index + 1)
    }
    return nil
  }

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

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


This code in my view controller works fine to control an added UIPageControl, but I can't get ahold of the default one:


    func configurePageControl() {
        self.pageControl.numberOfPages = 5
        self.pageControl.currentPage = photoIndex
        pageControl.transform = CGAffineTransform(scaleX: 2, y: 2); // Looks better!
        self.pageControl.tintColor = UIColor.blue  // This does nothing?
        self.pageControl.pageIndicatorTintColor = UIColor.red
        self.pageControl.currentPageIndicatorTintColor = UIColor.black      
        self.view.addSubview(pageControl)
    }

I've never used, so I'm not sure of what I propose.


Why do you addSubview

self.view.addSubview(pageControl)


What happens if you don't add, but just call setNeedsDisplay on the control ?



Another solution, if this one does not work:

In func configurePageControl() {


you could create a new pageControl:

var customPageControl = UIPageControl()


Then set its properties as you did

        customPageControlnumberOfPages = 5
        customPageControl.currentPage = photoIndex
        customPageControl.transform = CGAffineTransform(scaleX: 2, y: 2); // Looks better!
        //  customPageControl.tintColor = UIColor.blue          // It seems (from looking at other apps, that the tint is transparent, to keep the background tint
       // Try :
        customPageControl.pageIndicatorTintColor = UIColor.red          
        customPageControl.currentPageIndicatorTintColor = UIColor.black     // Would be more visible if this one was red ??


then add to the view and hide the previous one

       self.view.addSubview(customPageControl)
       self.pageControl.hidden = true     


You may have also to update customPageControl on page change.

"Why do you addSubview"

self.view.addSubview(pageControl)

It apparently makes no difference and I've omitted that line. I've been testing a lot of approaches and it was probably a leftover.


I should have shown a bit more. I already create my custom page control in Interface Builder. This is in the view controller where my data gets displayed.

@IBOutlet weak var pageControl: UIPageControl!


This makes it easy to place it where I want. If I use instead:

var pageControl = UIPageControl()

... and display it as a subview, it gets displayed in the upper left corner. I'm sure I could fix that but there's no gain.


"then add to the view and hide the previous one"

self.pageControl.hidden = true

The trouble is, there is no way I know of to reference the default pageControl. I can hide the UIPageControl I add myself, but cannot reference the default page control.

The other threads on this issue mention subclassing the default UIPageControl to alter the default dots. I may have the wording wrong, because I don't fully understand that process, but I think you get the drift. For an example, look at question #12190147 at StackOverflow. I'd be willing to maybe give that a try but I haven't found a complete example in Swift. Doing it myself from scratch is just too dauting.

So, you deleted the addSubview ?

Did you add the needsDisplay :


func configurePageControl() {
        self.pageControl.numberOfPages = 5
        self.pageControl.currentPage = photoIndex
        pageControl.transform = CGAffineTransform(scaleX: 2, y: 2); // Looks better!
        self.pageControl.tintColor = UIColor.blue  // This does nothing?
        self.pageControl.pageIndicatorTintColor = UIColor.red
        self.pageControl.currentPageIndicatorTintColor = UIColor.black      
        self.pageControl.needsDisplay = true
    }

I believe that is now:

self.pageControl.setNeedsDisplay()


I added that without any impact.


I don't understand the logic of adding that line. It's not a problem to get my custom page control dots to show properly. The problem is that I cannot control the appearance of the default dots, or make them disappear. My preference would be to use the default dots if I could only change their appearnace. I may just have to live with them the way they are.

>I may just have to live with them the way they are.


Echo that...or, as with many defaults, don't use a UIPVC at all, and just DIY the whole thing - you're halfway there now w/your custom dots, so...

Custom color and size for UIPageControl dots?
 
 
Q