在不同设备上无法正确呈现二次曲线

时间:2019-07-09 02:53:58

标签: swift drawing bezier quadratic-curve

我正在尝试绘制一条贝塞尔曲线,中间有一个二次曲线。该曲线在iPhone 8和XS上效果很好,但在其他设备上却没有响应(即无法正确渲染)。

下面是iPhone XS中曲线的图像(正确)

enter image description here

和iPhone XR(不正确)

enter image description here

我试图使用视图的约束来获取行的中间值,但是以某种方式它仍然无法工作

这是我绘制路径的代码:

//self.viewTabBorder is the grey line, which is a uiview with 1 pixel height
override func viewWillAppear(_ animated: Bool) {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: self.viewTabBorder.center.x - self.btnHome.frame.width + 20, y: 0))
        path.addQuadCurve(to: CGPoint(x: self.viewTabBorder.center.x + self.btnHome.frame.size.width - 20, y: 0), controlPoint: CGPoint(x: self.viewTabBorder.center.x, y: self.btnHome.frame.height + 5))
        path.addLine(to: CGPoint(x: self.viewTabBorder.center.x + self.btnHome.frame.size.width - 20, y: 0))

        let line = CAShapeLayer()
        line.path = path.cgPath
        line.strokeColor = UIColor(red: 224, green: 224, blue: 224).cgColor
        line.fillColor = UIColor.white.cgColor
        self.view.layer.addSublayer(line)
        self.viewTabBorder.layer.addSublayer(line)
    }

有人可以告诉我我所缺少的吗?提前非常感谢您!

1 个答案:

答案 0 :(得分:1)

一些观察结果:

  1. 您正在定义视图的子层的路径。在viewWillAppear中执行此操作还为时过早。应用约束可能无法完成布局引擎,将视图放置在其最终位置。在viewDidLayoutSubviews中而不是在viewWillAppear中(不是viewDidLoad也不是viewWillLayoutSubviews)中定义路径。

    这还具有以下优点:如果您更改应用程序以支持多种方向或进行任何会影响视图约束的更改,我们将再次调用此viewDidLayoutSubviews,以便可以根据需要正确更新这些子层。如果您使用viewWillAppear,则您的应用将不支持对视图的动态更改(您是否需要这样做)。

  2. 话虽如此,请注意viewDidLayoutSubviews可以被多次调用。因此,您可以例如在viewDidLoad中添加子层,但在viewDidLayoutSubviews中更新其路径。

  3. 在这里这可能不是问题,但我建议您在为子层定义路径时避免使用framecenter。请记住,这两个属性是在其 superview的坐标系中定义的。我建议您始终使用视图的bounds(在视图自身的坐标系中定义),而不要使用其{{ 1}}(在其父视图的坐标系中定义),当尝试为子层定义路径时。而且,例如,在定义子图层的路径时,如果需要视图的水平中心,请使用frame而不是bounds.midX

    有时候这无关紧要(如果视图在其超级视图中是从一边到另一边),但是(a)这表明对不同的坐标系有误解; (b)如果您曾经添加安全区域或以其他方式调整视图的位置,则使用center.x / frame会给您带来麻烦。


一个稍微高级的概念:一旦您遇到了直接的问题,您可以考虑将这种子视图配置移到center子类中(使用其UIView方法),甚至可能使其成为layoutSubviews类,因此您可以在Interface Builder中看到它。或者,另一种方法是将其包装在容器视图控制器中。但这两种方式都可以帮助防止视图控制器“膨胀”。这可能超出了此问题的范围,但是在您前进时需要考虑一些问题。