Ios 为UIPageControl中的点添加边框

Ios 为UIPageControl中的点添加边框,ios,uipagecontrol,Ios,Uipagecontrol,我想为UIPageControl中的点添加边框颜色。下面是它的小图片: 我可以通过XCode配置第二个点,但我不能使第一个和第三个圆的内部为空。有没有一个简单的方法来实现这一点 谢谢:)编辑-Swift 3&4扩展以获得相同的结果- extension UIPageControl { func customPageControl(dotFillColor:UIColor, dotBorderColor:UIColor, dotBorderWidth:CGFloat) {

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

我可以通过XCode配置第二个点,但我不能使第一个和第三个圆的内部为空。有没有一个简单的方法来实现这一点


谢谢:)

编辑-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()或ViewDidAspect()中编写以下代码

在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;
        }
    }
}
-(void)customPageControlWithFillColor:(UIColor*)dotFillColor borderColor:(UIColor*)dotBorderColor borderWidth:(CGFloat)dotBorderWidth{
对于(int pageIndex=0;pageIndex<\u pageControl.numberOfPages;pageIndex++){
UIView*dotView=[\u pageControl.subviews objectAtIndex:pageIndex];
if(_pageControl.currentPage==pageIndex){
dotView.backgroundColor=dotFillColor;
dotView.layer.cornerRadius=dotView.frame.size.height/2;
}否则{
dotView.backgroundColor=[UIColor clearColor];
dotView.layer.cornerRadius=dotView.frame.size.height/2;
dotView.layer.borderColor=dotBorderColor.CGColor;
dotView.layer.borderWidth=dotBorderWidth;
}
}
}
输出-


当前属性可用于
UIPageControl
,这是不可能的。但是您可以通过集成任何模仿iOS
UIPageControl
功能的页面控件来实现


另一个答案适用于修补程序。我非常不同意那个解决方案。

我正在使用。这是一个用Objective-C编写的非常棒的框架,因此它能够与Swift 2和Swift 3配合使用

用法非常简单:

pod 'SMPageControl'
然后在
页面视图控制器中

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

}
结果如下所示:


现在我们当然可以使用彩色点作为图像(空白颜色为未使用的颜色,填充颜色为使用的颜色),然后我们就可以得到要求的结果。

来自@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
        }
    }
}

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

这是如何做到的:

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

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

需要在ViewDidDisplay中添加此选项

pageControl.customPageControl(dotFillColor: .orange, dotBorderColor: .green, dotBorderWidth: 2)
 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;
        }
    }
for(int i=0;i<\u pageControl.numberOfPages;i++){
UIView*dot=[\u pageControl.subviews objectAtIndex:i];
if(i==\u pageControl.currentPage){
dot.backgroundColor=[UIColor whiteColor];
dot.layer.cornerRadius=dot.frame.size.height/2;
}否则{
dot.backgroundColor=[UIColor clearColor];
dot.layer.cornerRadius=dot.frame.size.height/2;
dot.layer.borderColor=[UIColor whiteColor].CGColor;
dot.layer.borderWidth=1;
}
}

只需添加这两行,然后添加所需的图像

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

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

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

}

Swift 5版本

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

卢克·罗杰斯的解决方案,用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;
}
现代卢克·罗杰斯(埃尔克·克罗纳说它不够现代,不适合ios14)


有其他方法可以实现这一点吗?@EmrahAkgül如果您在storyboard中设置页面控件,请尝试在
viewdide出现后调用
for
循环。这对我有用。当我在
viewDidLoad
中调用循环时,它不起作用。谢谢@riosk
borderColor
borderWidth
设置就足够了。其余的不用了<可以使用
pageIndicatorTintColor
currentPageIndicatorTintColor
设置状态的代码>背景颜色。投票支持这一点,因为它有帮助。请确保在视图出现后调用,如上面提到的@Therohansap@i在我的案例中显示它。请参阅附件。如果操作系统更新更改了视图层次结构,则在子视图上进行迭代可能随时中断。“其他答案已应用修补程序。”还有什么解决方案我必须在视图中添加call nice函数才能使其工作。在ios 14中不工作在ios 14中不工作
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
    }
    
}