1

Ich versuche, eine benutzerdefinierte segmentierte Steuerelement zu erstellen, die unter meiner Suche Controller sitzt, wie in der Mock-up unterErstellen von benutzerdefinierten segmentiert Steuerung mit Bezier-Pfad (Swift)

Segmented Control Mockup

Problem gesehen:

Ich habe Schwierigkeiten mit der Erstellung der spitzen Nadel (sieht so aus: "^"), die den aktuellen Index anzeigt.

Versuch einer Lösung:

Dank etwas Hilfe von der Frage unten, konnte ich es in der Nähe bekommen suchen, aber ich bin nicht in der Lage die Zeiger zu bekommen

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

enter image description here

Frage:

Wie bekomme ich meinen Code wie das Mockup mit dem, was ich derzeit habe und den Zeiger mit dem aktuellen Index des segmentierten Controllers bewegen? Siehe meinen Code unter

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); 

    } 

} 

Antwort

2

Der einfachste Weg, dies zu tun ist zu betrügen. Anstatt die Linie mit einer Bezierkurve zu zeichnen, können Sie einfach eine durchgezogene Linie zeichnen, indem Sie eine UIView mit einer Höhe von 1 verwenden. Machen Sie das Dreieck mit dem durchgehenden weißen Boden in PhotoShop als Bild und setzen Sie es über die Linie. Um nun die Position zu animieren, können Sie entweder ihre Transformation ändern, ihre Mitte aktualisieren oder automatische Layout-Einschränkungen verwenden und sie wird in die neue Position verschoben. Zum Beispiel:

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

Sie können dies natürlich auch programmgesteuert mit einem CAShapeLayer tun. Sie würden Ihren Weg Verwendung etwas entlang der Linien von konstruieren:

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() 

Dann Sie eine CABasicAnimation kann den Weg vom alten Pfad zum neuen animieren. Da Sie die Punkte in der gleichen Reihenfolge konstruieren, interpoliert das Animationssystem die Position und das Dreieck scheint in Position zu gleiten.

+0

Danke, Josh. Also ging ich voran und versuchte, die Linie mit einem bezeirPath zu zeichnen, um zu sehen, ob ich es programmatisch zur Arbeit bringen kann, aber ich bin unsicher, wie ich den CAShapeLayer zu meinem segmentierten Steuerelement hinzufügen kann. Nachdem ich den Pfad erstellt habe, wie bekomme ich es im segmentierten Steuerelement "zu zeigen"? –

+0

Sie müssen Ihren Layer in viewDidLayoutSubviews erstellen, damit er immer korrekt dimensioniert wird. (Wenn die Ebene vorhanden ist, entfernen Sie "FromSuperlayer" und erstellen Sie eine neue CAShape-Ebene.) Setzen Sie shapeLayer.path = bezierPath.cgPath. Sie müssen auch die Linienbreiten- und Strichfarbe festlegen. Fügen Sie schließlich Ihre Shape-Ebene als Unterebene dem view.layer Ihres segmentierten Steuerelements hinzu. Wenn Sie mit Layern nicht vertraut sind, ist es einfacher, dies mit der ersten Methode zu tun, die ich nur mit UIView beschrieben habe. –

+0

Das war eine brillante Lösung! Ich ging mit dem Ansatz, eine UIView mit einem weißen unteren Rand zu verwenden. Danke für die Hilfe, Josh! –

Verwandte Themen