使用贝塞尔曲线路径创建自定义分段控件 (Swift)

Create custom segmented control using bezier path (Swift)

我正在尝试创建一个位于我的搜索控制器下方的自定义分段控件,如下面的模型所示

问题

我在创建指示当前索引的尖针(看起来像这样:“^”)时遇到困难。

尝试解决方案:

多亏了下面问题的帮助,我能够让它看起来很接近,但我无法让指针显示出来

问题:

如何让我的代码看起来像我当前拥有的模型,并让指针随着分段控制器的当前索引移动?请参阅下面的代码

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

    }

}

最简单的方法就是作弊。您可以使用高度为 1 的 UIView 绘制实线,而不是使用贝塞尔曲线绘制线。在 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 为从旧路径到新路径的路径设置动画。由于您以相同的顺序构建点,因此动画系统将插入位置并且三角形看起来会滑入位置。