Добавить границу для точек в UIPageControl
Я хочу добавить цвет границы для точек в UIPageControl. Вот небольшая картина:
Я могу поставить вторую точку, настроив ее из XCode, но я не могу сделать первый и третий круги пустыми. Есть ли простой способ достичь этого?
Благодаря :)
Ответы
Ответ 1
Это невозможно с текущими свойствами, доступными для UIPageControl
. Но вы можете сделать, интегрируя любой элемент управления третьей стороной, который имитирует функциональность iOS UIPageControl
.
Другой ответ применил патч.Я очень не согласен с этим решением.
Ответ 2
Edited- Swift 3 & 4 расширение для достижения того же 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
}
}
}
}
чтобы использовать его, напишите код ниже в viewDidLoad() или viewDidAppear()
pageControl.customPageControl(dotFillColor: .orange, dotBorderColor: .green, dotBorderWidth: 2)
В Objective-C используйте ниже 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-
Ответ 3
Другим подходом было бы использовать образ образца правильного размера (который в настоящее время составляет 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
}
}
Недостатком этого является то, что если размер точки изменяется в обновлении ОС, изображение будет выглядеть странно, поскольку оно будет выгравировано или обрезано.
Ответ 4
Версия SWIFT 3 от @RiosK
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
}
}
}
Ответ 5
Я использую SMPageControl. Это действительно потрясающая платформа, написанная в Objective-C, поэтому она способна с Swift 2 и Swift 3.
Использование полностью прост:
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 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
}
}
Результат выглядит следующим образом:
Теперь мы можем, конечно, использовать цветные точки в качестве изображений (пустые цветные как неиспользуемые и заполненные цветом, как используется), тогда мы получили бы заданный результат.
Ответ 6
Просто добавьте две строки и добавьте желаемое изображение!
pageControl.currentPageIndicatorTintColor = UIColor.init(patternImage: UIImage(named: "slider_selected")!)
pageControl.pageIndicatorTintColor = UIColor.init(patternImage: UIImage(named: "slider")!)
Ответ 7
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
}
}
}
}
Ответ 8
Необходимо добавить это в 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;
}
}
Ответ 9
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
}
}
Ответ 10
Решение Люка Роджерса, написанное в target-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;
}