【问题标题】:Quadratic curve not rendered correctly on different devices二次曲线未在不同设备上正确渲染
【发布时间】:2019-07-09 02:53:58
【问题描述】:

我正在尝试绘制一条中间有二次曲线的贝塞尔路径。该曲线在 iPhone 8 和 XS 上运行良好,但在其他设备上没有响应(即未正确渲染)。

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

和 iPhone XR(不正确)

我尝试使用视图的约束来获取行的中间值,但不知何故它仍然无法正常工作

这是我绘制路径的代码:

//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)
    }

谁能告诉我我错过了什么?非常感谢您!

【问题讨论】:

  • 上传分析器的屏幕截图,否则人们无事可做
  • @Alexander 抱歉,我还是 swift 新手。你能告诉我探查器到底是什么吗?
  • @Alexander 谢谢你的链接。下面是我刚刚截取的分析器截图的链接:imgur.com/a/Bx9c8WA
  • 不相关,但是当您覆盖任何这些视图生命周期方法时,始终调用super 实现也是谨慎的做法。

标签: swift drawing bezier quadratic-curve


【解决方案1】:

几个观察:

  1. 您正在定义子层到视图的路径。在viewWillAppear 中这样做还为时过早。布局引擎可能没有完成应用约束,将视图放置在它们的最终位置。在viewDidLayoutSubviews 中定义路径,而不是在viewWillAppear 中(也不是viewDidLoad,也不是viewWillLayoutSubviews)。

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

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

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

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


一个稍微高级一点的概念:一旦你解决了眼前的问题,你可能会考虑将这个子视图配置移动到一个UIView 子类中(使用它的layoutSubviews 方法),甚至可能使它成为一个@IBDesignable 类所以你可以在 Interface Builder 中看到这个渲染。或者,另一种方法是将其包装在容器视图控制器中。但无论哪种方式,这都有助于防止视图控制器“膨胀”。这可能有点超出了这个问题的范围,但是在你前进的过程中需要考虑一些事情。

【讨论】:

  • 感谢您的详尽解释。按照您的指示执行步骤解决了问题!我还将尝试您建议的其他概念。完全节省了我的一天
猜你喜欢
  • 2015-08-21
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多