在UIPageControl中添加点的边框

时间:2016-03-07 11:02:24

标签: ios uipagecontrol

我想在UIPageControl中为点添加边框颜色。这是它的小图片:

enter image description here

我可以通过从XCode配置它来放置第二个点,但是我不能创建第一个和第三个圆圈'里面空着。有没有一种简单的方法来实现这一目标?

谢谢:)

12 个答案:

答案 0 :(得分:19)

编辑 - Swift 3& 4扩展以实现相同的结果 -

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
            }
        }
    }

}

使用它在viewDidLoad()或viewDidAppear()

中写下面的代码
pageControl.customPageControl(dotFillColor: .orange, dotBorderColor: .green, dotBorderWidth: 2)

Objective-C 中使用以下代码 -

- (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;
        }
    }
}

输出 -

enter image description here

答案 1 :(得分:18)

另一种方法是使用正确尺寸的图案图像(目前直径为7个点)。这是结果如下:

Pagination dots screenshot

以及它是如何完成的:

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

使用这个简单的小扩展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
    }
}

这样做的缺点是,如果在操作系统更新中点大小发生变化,图像看起来会很奇怪,因为它会被平铺或剪裁。

答案 2 :(得分:15)

来自@RiosK的

SWIFT 3版

func updatePageControl() {
    for (index, dot) in pageControl.subviews.enumerated() {
        if index == pageControl.currentPage {
            dot.backgroundColor = dotColor
            dot.layer.cornerRadius = dot.frame.size.height / 2;
        } else {
            dot.backgroundColor = UIColor.clear
            dot.layer.cornerRadius = dot.frame.size.height / 2
            dot.layer.borderColor = dotColor.cgColor
            dot.layer.borderWidth = dotBorderWidth
        }
    }
}

答案 3 :(得分:6)

UIPageControl的当前属性无法实现。但您可以通过集成模仿iOS UIPageControl功能的任何third party页面控件来实现。

其他答案已应用补丁。我非常不同意这个解决方案。

答案 4 :(得分:2)

我正在使用SMPageControl。它是一个用Objective-C编写的非常棒的框架,所以它能够使用Swift 2和Swift 3。

enter image description here

用法非常简单:

pod 'SMPageControl'

然后在PageViewController

import SMPageControl

class MyController: UIPageViewController {

     var pageControl = SMPageControl()

     override func viewDidLoad() {
        super.viewDidLoad()

        stylePageControl()
    }

private func stylePageControl() {

    pageControl = SMPageControl(frame: CGRect(x: 0, y: self.view.frame.size.height - 50, width: self.view.frame.size.width, height: 50))
    pageControl.numberOfPages = yourPageControllerArray.count

//  the first (first) picture is the item in the bar, that is unused
//  the second (currentFirst) is an item that we use, when this is the current active page
//  in this example, we don't have dots, but we use "pictues" as dots

    let first = UIImage(named: "pageHome")?.imageWithColor(UIColor.grayColor())
    let currentFirst = first?.imageWithColor(UIColor.whiteColor())

    pageControl.setImage(first, forPage: 0)
    pageControl.setCurrentImage(currentFirst, forPage: 0)

    let second = UIImage(named: "pageMusic")?.imageWithColor(UIColor.grayColor())
    let currentSecond = second?.imageWithColor(UIColor.whiteColor())

    pageControl.setImage(second, forPage: 1)
    pageControl.setCurrentImage(currentSecond, forPage: 1)

    pageControl.indicatorMargin = 30.0 // this is the space between the dots

    self.view.addSubview(pageControl)
}

UIImage Extension我已经使用过:

extension UIImage {

    func imageWithColor(color1: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color1.setFill()

        let context = UIGraphicsGetCurrentContext()! as CGContextRef
        CGContextTranslateCTM(context, 0, self.size.height)
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, CGBlendMode.Normal)

        let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect
        CGContextClipToMask(context, rect, self.CGImage!)
        CGContextFillRect(context, rect)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage
        UIGraphicsEndImageContext()

        return newImage
    }

}

结果如下:

enter image description here

现在我们当然可以使用彩色圆点作为图像,(空白颜色为未使用颜色并使用颜色填充)然后我们会得到询问结果。

答案 5 :(得分:1)

只需添加这两行并添加所需的图像!!

pageControl.currentPageIndicatorTintColor  = UIColor.init(patternImage: UIImage(named: "slider_selected")!)

pageControl.pageIndicatorTintColor =  UIColor.init(patternImage: UIImage(named: "slider")!)

答案 6 :(得分:0)

需要在viewDidAppear

中添加此内容
 for (int i = 0; i < _pageControl.numberOfPages; i++) {
        UIView* dot = [_pageControl.subviews objectAtIndex:i];
        if (i == _pageControl.currentPage) {
            dot.backgroundColor = [UIColor whiteColor];
            dot.layer.cornerRadius = dot.frame.size.height / 2;
        } else {
            dot.backgroundColor = [UIColor clearColor];
            dot.layer.cornerRadius = dot.frame.size.height / 2;
            dot.layer.borderColor = [UIColor whiteColor].CGColor;
            dot.layer.borderWidth = 1;
        }
    }

答案 7 :(得分:0)

快捷键4 。您可以分配borderColor,然后观察currentPage属性以更改点的边框:

class CustomPageControl: UIPageControl {

    var borderColor: UIColor = .clear

    override var currentPage: Int {
        didSet {
            updateBorderColor()
        }
    }

    func updateBorderColor() {
        subviews.enumerated().forEach { index, subview in
            if index != currentPage {
                subview.layer.borderColor = borderColor.cgColor
                subview.layer.borderWidth = 1
            } else {
                subview.layer.borderWidth = 0
            }
        }
    }

}

答案 8 :(得分:0)

Swift 5 版本

post

答案 9 :(得分:0)

卢克·罗杰斯(Luke Rogers)的解决方案,用Objective-C编写:

-(UIImage *) outlinedEllipse:(CGSize)size color: (UIColor*) lineColor width:(CGFloat) lineWidth {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0);

        CGContextRef context = UIGraphicsGetCurrentContext();
        if (context == NULL) {
            return NULL;
        }

        CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
        CGContextSetLineWidth(context, lineWidth);
        // Inset the rect to account for the fact that strokes are
        // centred on the bounds of the shape.

        CGRect rect = CGRectInset(CGRectMake(0, 0, 7.0f, 7.0f), lineWidth * 0.5, lineWidth * 0.5);
        CGContextAddEllipseInRect(context, rect);
        CGContextStrokePath(context);

        UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
}

答案 10 :(得分:0)

现代卢克·罗杰斯

extension UIImage
{
// https://stackoverflow.com/questions/35842040/add-border-for-dots-in-uipagecontrol
    // modernized Luke Rogers
    class func outlinedEllipse(size: CGSize, color: UIColor, lineWidth: CGFloat = 1.0) -> UIImage? {

        let renderer = UIGraphicsImageRenderer(size: size)
        let image = renderer.image { context in

            color.setFill()

            context.cgContext.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.cgContext.strokeEllipse(in: rect)
        }
        return image
    }

}

答案 11 :(得分:0)

请尝试 UIPageControl 的自定义子类化。 iOS 14 允许使用 SFSymbol 设置指示器图像。

class BorderedPageControl: UIPageControl {

    var selectionColor: UIColor = .black
    
    override var currentPage: Int {
        didSet {
            updateBorderColor()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        currentPageIndicatorTintColor = selectionColor
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    func updateBorderColor() {
        if #available(iOS 14.0, *) {
            let smallConfiguration = UIImage.SymbolConfiguration(pointSize: 8.0, weight: .bold)
            let circleFill = UIImage(systemName: "circle.fill", withConfiguration: smallConfiguration)
            let circle = UIImage(systemName: "circle", withConfiguration: smallConfiguration)
            for index in 0..<numberOfPages {
                if index == currentPage {
                    setIndicatorImage(circleFill, forPage: index)
                } else {
                    setIndicatorImage(circle, forPage: index)
                }
            }
            pageIndicatorTintColor = selectionColor
        } else {
            subviews.enumerated().forEach { index, subview in
                if index != currentPage {
                    subview.layer.borderColor = selectionColor.cgColor
                    subview.layer.borderWidth = 1
                } else {
                    subview.layer.borderWidth = 0
                }
            }
        }
    }
}