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

标签 swift core-graphics uisegmentedcontrol uibezierpath uigraphicscontext

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

Segmented Control Mockup

问题:

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

尝试解决方案:

感谢以下问题的一些帮助,我能够让它看起来很接近,但我无法让指针显示出来

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

enter image description here

问题:

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

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 将路径从旧路径动画化到新路径。由于您以相同的顺序构造点,动画系统将插入位置,并且三角形将显示为滑入位置。

关于swift - 使用贝塞尔路径创建自定义分段控件(Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40517176/

相关文章:

macos - 显示 CGContextRef

ios - 为什么我的 for 循环不正确地增加 strokeColor

导航栏中的 iOS 分段控件

ios - 使用 UIColor(patternImage :) for UIView's tintColor?

swift - 参数类型相同但范围不同的重载函数

string - 在 Swift 中从字符串到 NSDate

iphone - ios View 坐标系

ios - 无法将分段控件添加到 ios 7 中的警报 View

swift - 如何检测该参数是两种任意类型的元组?

ios - 多个 UILabels 点击相同的 UITapGestureRecogniser 不工作