简体   繁体   English

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

[英]Quadratic curve not rendered correctly on different devices

I'm trying to draw a bezier path with a quadratic curve in the middle.我正在尝试绘制一条中间有二次曲线的贝塞尔曲线。 The curve works well on iPhone 8 and XS, but is not responsive (ie not rendered correctly) on other devices.该曲线在 iPhone 8 和 XS 上运行良好,但在其他设备上没有响应(即未正确呈现)。

Below is the image of the curve in iPhone XS (correct)下面是 iPhone XS 中的曲线图(正确)

在此处输入图片说明

and iPhone XR (incorrect)和 iPhone XR(不正确)

在此处输入图片说明

I've tried to use the view's constraint to get the middle value of the line but somehow it still not working我试图使用视图的约束来获取行的中间值,但不知何故它仍然无法正常工作

Here is the code where i'm drawing the path:这是我绘制路径的代码:

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

Can anyone show me what i'm missing?谁能告诉我我错过了什么? Thank you very much in advance!非常感谢您提前!

A couple of observations:几个观察:

  1. You are defining paths for sublayers to views.您正在定义子图层到视图的路径。 Doing this in viewWillAppear is too early in the process.viewWillAppear这样做还为时过早。 The layout engine may not be done applying constraints, placing the views in their final location.布局引擎可能没有完成应用约束,将视图放置在它们的最终位置。 Do the defining of the paths in viewDidLayoutSubviews , not in viewWillAppear (nor viewDidLoad , nor viewWillLayoutSubviews ).viewDidLayoutSubviews定义路径,而不是在viewWillAppear (也不是viewDidLoad ,也不是viewWillLayoutSubviews )中。

    This also has the virtue that should you ever change your app to support multiple orientations or do any changes that affect the constraints in the view, this viewDidLayoutSubviews we be called again so these sublayers will be properly updated as needed.这也有一个优点,如果您更改应用程序以支持多个方向或进行任何影响视图中约束的更改,我们将再次调用此viewDidLayoutSubviews ,以便根据需要正确更新这些子层。 If you use viewWillAppear your app will not support dynamic changes to your views (should you ever need that).如果您使用viewWillAppear您的应用程序将不支持对您的视图进行动态更改(如果您需要的话)。

  2. That having been said, be aware that viewDidLayoutSubviews can be called multiple times.话虽如此,请注意可以多次调用viewDidLayoutSubviews So you can, for example, add the sublayers in viewDidLoad , but update their paths in viewDidLayoutSubviews .所以,你可以,例如,添加的子层viewDidLoad的,但更新他们的路径viewDidLayoutSubviews

  3. It is likely not an issue here, but I would suggest you avoid using frame or center when defining a path for a sublayer.这在这里可能不是问题,但我建议您在为子图层定义路径时避免使用framecenter Remember that these two properties are defined in the coordinate system of their superview.请记住,这两个属性是在其父视图的坐标系中定义的 I'd suggest you always use a view's bounds (defined in a view's own coordinate system), not its frame (defined in its superview's coordinate system) when trying to define a path for a sublayer.我建议您在尝试为子图层定义路径时,始终使用视图的bounds (在视图自己的坐标系中定义),而不是其frame (在其超级视图的坐标系中定义)。 And if you want, for example, the horizontal center of a view when defining a sublayer's path, use bounds.midX not center.x .例如,如果您想在定义子图层路径时使用视图的水平中心,请使用bounds.midX而不是center.x

    Sometimes this won't matter (if the view goes edge-to-edge within its superview), but (a) it suggests a misunderstanding of the different coordinate systems;有时这无关紧要(如果视图在其父视图中是边到边的),但是 (a) 它表明对不同坐标系的误解; and (b) if you ever add safe areas or otherwise adjust the placement of the view, using the frame / center will get you into trouble. (b) 如果您添加安全区域或以其他方式调整视图的位置,使用frame / center会给您带来麻烦。


A slightly more advanced concept: Once you have your immediate issue behind you, you might consider moving this configuration of subviews into a UIView subclass (using its layoutSubviews method), possibly even making it an @IBDesignable class so you can see this rendered in Interface Builder.一个稍微高级一点的概念:一旦你解决了眼前的问题,你可能会考虑将子视图的这个配置移动到UIView子类中(使用它的layoutSubviews方法),甚至可能使它成为一个@IBDesignable类,这样你就可以看到它在界面中呈现建设者。 Or, another approach is to wrap this in a container view controller.或者,另一种方法是将其包装在容器视图控制器中。 But either way, this can help prevent view controller “bloat”.但无论哪种方式,这都有助于防止视图控制器“膨胀”。 It's probably a bit beyond the scope of this question, but something to consider as you move forward.这可能有点超出了这个问题的范围,但在你前进的过程中需要考虑一些事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM