Add border for dots in UIPageControl

Another approach would be to use a pattern image of the correct size (which currently is 7 points in diameter). Here's what the result looks like:

Pagination dots screenshot

And here's how it's done:

let image = UIImage.outlinedEllipse(size: CGSize(width: 7.0, height: 7.0), color: .darkGray)
self.pageControl.pageIndicatorTintColor = UIColor.init(patternImage: image!)
self.pageControl.currentPageIndicatorTintColor = .darkGray

Which uses this simple little extension to UIImage:

/// An extension to `UIImage` for creating images with shapes.
extension UIImage {

    /// Creates a circular outline image.
    class func outlinedEllipse(size: CGSize, color: UIColor, lineWidth: CGFloat = 1.0) -> UIImage? {

        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        guard let context = UIGraphicsGetCurrentContext() else {
                return nil
        }

        context.setStrokeColor(color.cgColor)
        context.setLineWidth(lineWidth)
        // Inset the rect to account for the fact that strokes are
        // centred on the bounds of the shape.
        let rect = CGRect(origin: .zero, size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5)
        context.addEllipse(in: rect)
        context.strokePath()

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

The downside of this is that if the dot size changes in an OS update, the image will look weird as it will be tiled or clipped.


Edited- Swift 3 & 4 extension to achieve the same result-

extension UIPageControl {

    func customPageControl(dotFillColor:UIColor, dotBorderColor:UIColor, dotBorderWidth:CGFloat) {
        for (pageIndex, dotView) in self.subviews.enumerated() {
            if self.currentPage == pageIndex {
                dotView.backgroundColor = dotFillColor
                dotView.layer.cornerRadius = dotView.frame.size.height / 2
            }else{
                dotView.backgroundColor = .clear
                dotView.layer.cornerRadius = dotView.frame.size.height / 2
                dotView.layer.borderColor = dotBorderColor.cgColor
                dotView.layer.borderWidth = dotBorderWidth
            }
        }
    }

}

to use it write below code in viewDidLoad() or viewDidAppear()

pageControl.customPageControl(dotFillColor: .orange, dotBorderColor: .green, dotBorderWidth: 2)

In Objective-C use below code-

- (void) customPageControlWithFillColor:(UIColor*)dotFillColor borderColor:(UIColor*)dotBorderColor borderWidth:(CGFloat)dotBorderWidth {
    for (int pageIndex = 0; pageIndex < _pageControl.numberOfPages; pageIndex++) {
        UIView* dotView = [_pageControl.subviews objectAtIndex:pageIndex];
        if (_pageControl.currentPage == pageIndex) {
            dotView.backgroundColor = dotFillColor;
            dotView.layer.cornerRadius = dotView.frame.size.height / 2;
        } else {
            dotView.backgroundColor = [UIColor clearColor];
            dotView.layer.cornerRadius = dotView.frame.size.height / 2;
            dotView.layer.borderColor = dotBorderColor.CGColor;
            dotView.layer.borderWidth = dotBorderWidth;
        }
    }
}

Output-

enter image description here