1

Я пытаюсь создать пользовательский сегментированные управления, который находится под моим поиска контроллера, как показано на издеваться вверх нижеСоздание пользовательских сегментированный управления с использованием пути Безье (Swift)

Segmented Control Mockup

Проблема:

У меня возникли трудности с созданием заостренной иглы (выглядит так: «^»), которая указывает текущий индекс.

Попытка решения:

Благодаря некоторой помощи, используя вопрос, я был в состоянии получить его смотреть близко, но я не могу получить указатель, чтобы показать

https://stackoverflow.com/a/37705692/5254240

enter image description here

Вопрос:

Как получить код, похожий на макет с тем, что у меня есть, и заставить указатель перемещаться с текущим индексом сегментированного контроллера? См. Мой код ниже

func imageWithColor(color: UIColor) -> UIImage { 

    let rect = CGRectMake(0.0, 0.0, 1.0, segmentedController.frame.size.height) 
    UIGraphicsBeginImageContext(rect.size) 
    let context = UIGraphicsGetCurrentContext() 
    CGContextSetFillColorWithColor(context, color.CGColor); 
    CGContextFillRect(context, rect); 
    let image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return image 

} 

func initializeSearchController() { 
    segmentedController.setTitleTextAttributes([NSFontAttributeName:UIFont(name: "Lato-Regular", size: 14)!,NSForegroundColorAttributeName:UIColor.init(red: 143/255, green: 142/255, blue: 148/255, alpha: 1.0)], forState:UIControlState.Normal) 

    segmentedController.setTitleTextAttributes([NSFontAttributeName:UIFont(name: "Lato-Bold", size: 14)!,NSForegroundColorAttributeName:UIColor.init(red: 93/255, green: 176/255, blue: 175/255, alpha: 1.0)], forState:UIControlState.Selected) 

    segmentedController.setDividerImage(self.imageWithColor(UIColor.clearColor()), forLeftSegmentState: UIControlState.Normal, rightSegmentState: UIControlState.Normal, barMetrics: UIBarMetrics.Default) 

    segmentedController.setBackgroundImage(self.imageWithColor(UIColor.clearColor()), forState:UIControlState.Normal, barMetrics:UIBarMetrics.Default) 

    segmentedController.setBackgroundImage(self.imageWithColor(UIColor.clearColor()), forState:UIControlState.Selected, barMetrics:UIBarMetrics.Default) 

    segmentedController.setTitle("Search", forSegmentAtIndex: 0) 
    segmentedController.setTitle("Meals", forSegmentAtIndex: 1) 

    for borderview in segmentedController.subviews { 

     let upperBorder: CALayer = CALayer() 
     upperBorder.backgroundColor = UIColor.init(red: 93/255, green: 176/255, blue: 175/255, alpha: 1.0).CGColor 
     upperBorder.frame = CGRectMake(0, borderview.frame.size.height-1, borderview.frame.size.width, 1.0); 
     borderview.layer.addSublayer(upperBorder); 

    } 

} 

ответ

2

Самый простой способ сделать это - обмануть. Вместо того, чтобы рисовать линию кривой безье, вы можете просто нарисовать сплошную линию, используя UIView с высотой 1. Сделайте треугольник с сплошным белым дном в PhotoShop как изображение и поместите его поверх линии. Теперь, чтобы анимировать позицию, вы можете либо изменить ее преобразование, обновить его центр или использовать ограничения автоопределения, и он переместится в новую позицию. Например:

UIView.animate(withDuration: 0.25) { 
    triangeImageView.center.x = selectedLabel.center.x 
} 

Вы также можете сделать это программно, используя CAShapeLayer. Вы будете строить свой путь использовать что-то вдоль линий:

let bezierPath = UIBezierPath() 
bezierPath.move(to: CGPoint(x: left, y: bottom)) 
bezierPath.addLine(to: CGPoint(x: centerX + triangleWidth/2, y: top)) 
bezierPath.addLine(to: CGPoint(x: centerX, y: top - triangleHeight)) 
bezierPath.addLine(to: CGPoint(x: centerX - triangleWidth/2, y: top)) 
bezierPath.addLine(to: CGPoint(x: left, y: top)) 
bezierPath.close() 

Затем вы можете использовать CABasicAnimation анимировать путь от старого пути к новому. Поскольку вы строите точки в том же порядке, анимационная система будет интерполировать позицию, и треугольник, как представляется, сдвинется в нужное положение.

+0

Спасибо, Джош. Поэтому я пошел дальше и попытался нарисовать строку с bezeirPath, чтобы посмотреть, могу ли я заставить ее работать программно, но я не уверен, как добавить CAShapeLayer в мой сегментированный элемент управления. После того, как я создаю путь, как мне его «показать» в сегментированном элементе управления? –

+0

Вам нужно создать свой слой в viewDidLayoutSubviews, чтобы он всегда правильно сортировался. (т. е. если слой существует, removeFromSuperlayer и создать новый слой CAShape), установите shapeLayer.path = bezierPath.cgPath. Вам также необходимо установить цвет линии и штрих. Наконец, добавьте свой слой формы как подуровень в view.layer вашего сегментированного элемента управления. Если вы не знакомы со слоями, проще это сделать, используя первый метод, который я описал только с UIView. –

+0

Это было блестящее решение! Я пошел с использованием UIView с белой нижней границей. Спасибо за помощь, Джош! –