自定义 UIView 的子视图 x 帧位置错误 [英] Subview of Custom UIView has wrong x frame position

查看:18
本文介绍了自定义 UIView 的子视图 x 帧位置错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的自定义 UIView:

I have a custom UIView like so:

import UIKit

class MainLogoAnimationView: UIView {

    @IBOutlet var customView: UIView!
    var turquoiseCircle: AnimationCircleView!
    var redCircle: AnimationCircleView!
    var blueCircle: AnimationCircleView!


    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    func setup() {
        _ = Bundle.main.loadNibNamed("MainLogoAnimationView", owner: self, options: nil)?[0] as! UIView
        self.addSubview(customView)
        customView.frame = self.bounds
        setupAnimation()
    }

    let initialWidthScaleFactor: CGFloat = 0.06

    func setupAnimation() {
        let circleWidth = frame.size.width*initialWidthScaleFactor
        let yPos = frame.size.height/2 - circleWidth/2
        turquoiseCircle = AnimationCircleView(frame: CGRect(x: 0, y: yPos, width: circleWidth, height: circleWidth))
        turquoiseCircle.circleColor = UIColor(red: 137/255.0, green: 203/255.0, blue: 225/255.0, alpha: 1.0).cgColor
        turquoiseCircle.backgroundColor = UIColor.lightGray
        addSubview(turquoiseCircle)
        redCircle = AnimationCircleView(frame: CGRect(x: 100, y: yPos, width: circleWidth, height: circleWidth))
        addSubview(redCircle)
        blueCircle = AnimationCircleView(frame: CGRect(x: 200, y: yPos, width: circleWidth, height: circleWidth))
        blueCircle.circleColor = UIColor(red: 93/255.0, green: 165/255.0, blue: 213/255.0, alpha: 1.0).cgColor
        addSubview(blueCircle)
    }
}

我在界面构建器中创建了一个浅蓝色的 UIView,并将上面的视图 MainLogoAnimationView 设置为它的子类.如果我运行该应用程序,我会得到这个:

I created a light blue colored UIView in interface builder and set the above view MainLogoAnimationView as its subclass. If I run the app I get this:

似乎对于 turquoiseCircle 框架没有像我设置的那样放置在 x = 0 处.不确定我在这里做错了什么.是不是因为它是在MainLogoAnimationView 完全初始化之前放置的所以放置不正确?我尝试在 layoutSubviews() 中设置圆圈的框架,这也没有任何区别.我似乎经常遇到这个问题,因为视图放错了位置,并认为我在这里遗漏了一些基本的东西.我做错了什么?

It seems that for the turquoiseCircle the frame hasn't been placed at x = 0 as I set it. Not sure what I am doing wrong here. Is it because it is placed before the MainLogoAnimationView is fully initialized so being placed incorrectly? I have tried setting the frames of the circles in layoutSubviews() and this also didn't make any difference. I seem to run into the problem a lot with views being misplaced and think I am missing something fundamental here. What am I doing wrong?

更新:

import UIKit

class MainLogoAnimationView: UIView {

    @IBOutlet var customView: UIView!
    var turquoiseCircle: AnimationCircleView!
    var redCircle: AnimationCircleView!
    var blueCircle: AnimationCircleView!


    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    func setup() {
        _ = Bundle.main.loadNibNamed("MainLogoAnimationView", owner: self, options: nil)?[0] as! UIView
        self.addSubview(customView)
        customView.frame = self.bounds
        setupAnimation()
    }

    let initialWidthScaleFactor: CGFloat = 0.2


    func setupAnimation() {
        blueCircle = AnimationCircleView()
        blueCircle.translatesAutoresizingMaskIntoConstraints = false
        blueCircle.backgroundColor = UIColor.lightGray
        blueCircle.circleColor = UIColor.blue.cgColor
        addSubview(blueCircle)

        redCircle = AnimationCircleView()
        redCircle.translatesAutoresizingMaskIntoConstraints = false
        redCircle.backgroundColor = UIColor.lightGray
        addSubview(redCircle)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        let circleWidth = bounds.size.width*initialWidthScaleFactor
        let yPos = frame.size.height/2 - circleWidth/2
        blueCircle.frame = CGRect(x: 0, y: yPos, width: circleWidth, height: circleWidth)
        redCircle.frame = CGRect(x: frame.size.width/2 - circleWidth/2, y: yPos, width: circleWidth, height: circleWidth)
    }
}

和:

导入 UIKit

class AnimationCircleView: UIView {

    var circleColor = UIColor(red: 226/255.0, green: 131/255.0, blue: 125/255.0, alpha: 1.0).cgColor {
        didSet {
            shapeLayer.fillColor = circleColor
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    let shapeLayer = CAShapeLayer()

    func setup() {
        let circlePath = UIBezierPath(ovalIn: self.bounds)
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = circleColor
        shapeLayer.frame = self.bounds
        layer.addSublayer(shapeLayer)
    }

}

推荐答案

init 中的设置肯定会提供 self.frame/self.bounds无论视图的初始化值是什么,在视图层次结构中布局时都不是正确的最终值.处理这个问题的最好方法可能就像您尝试过的那样,在 init 中添加视图,并使用属性来保持对它们的引用(您已经这样做了),然后在 -layoutSubviews().

It's definitely the case that the setting up in init will provide self.frame/self.bounds values for whatever the view's initialized values are and not the correct final values when laid out in the view hierarchy. Probably the best way to handle this is like you tried, to add the views in init, and use property to keep a reference to them (you already are doing this) and then set the frame in -layoutSubviews().

它可能在 -layoutSubviews() 中不起作用的原因是对于创建后的每个视图,您需要调用 .translatesAutoresizingMaskIntoConstraints = false.否则,对于以编程方式创建的视图,系统将在作为子视图添加时为值创建约束,覆盖任何框架设置.尝试设置它,看看它是如何进行的.

The reason it probably didn't work in -layoutSubviews() is for each view after creation you need to call .translatesAutoresizingMaskIntoConstraints = false. Otherwise with programmatically-created views the system will create constraints for the values when added as a subview, overriding any setting of frames. Try setting that and see how it goes.

为了调整 CAShapeLayer 的大小,而不是作为子层添加(这需要手动调整大小),因为 AnimationCirleView 视图是专门的,该视图可以由 CAShapeLayer 支持.请参阅 在 swift 中覆盖 UIView 中的默认图层类型 中的答案

For resizing the CAShapeLayer, instead of adding as a sublayer (which would require manually resizing) since AnimationCirleView view is specialized the view can be backed by CAShapeLayer. See the answer at Overriding default layer type in UIView in swift

这篇关于自定义 UIView 的子视图 x 帧位置错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆