以编程方式添加自定义视图时,自定义视图不可见,但在使用故事板添加时,它是可见的

时间:2017-12-29 12:22:11

标签: ios swift

我有自己的自定义视图,就像进度条一样。这是代码:

class ProgressBar: UIView {

    var bottomProgressBar = CAShapeLayer()
    var topProgressBar = CAShapeLayer()

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

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

    func configure() {
        bottomProgressBar.strokeColor = UIColor.white.cgColor
        bottomProgressBar.opacity = 0.1
        bottomProgressBar.lineWidth = self.frame.height
        bottomProgressBar.strokeStart = 0
        bottomProgressBar.strokeEnd = 1
        self.layer.addSublayer(bottomProgressBar)

        topProgressBar.strokeColor = UIColor.white.cgColor
        topProgressBar.lineWidth = self.frame.height
        topProgressBar.strokeStart = 0
        topProgressBar.strokeEnd = 1
        self.layer.addSublayer(topProgressBar)

        animate(toValue: 0)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath()
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: self.frame.width, y: 0))

        bottomProgressBar.path = path.cgPath
        topProgressBar.path = path.cgPath
    }
}

现在,当我使用故事板添加此内容时,在控制器中添加UIView并将Custom Class设置为ProgressBar我可以在运行应用时看到它(它应该有白色,含α0.1)。

但是当我试图以编程方式添加时,它根本不可见。只有我明确设置背景颜色:

myProgressBar.backgroudColor = .red

这不是我想要的。我希望它具有白色和alpha 0.1即初始值。

以下是我以编程方式添加代码的代码:

var progressBar = ProgressBar()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(progressBar)

        progressBar.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint(item: progressBar, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: progressBar, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: progressBar, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true
        NSLayoutConstraint(item: progressBar, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 1).isActive = true
    }

我似乎不明白使用故事板添加它并以编程方式添加它之间有什么区别。
我看到约束是正确的并且添加了视图,但为什么不显示默认颜色?

在这种情况下,有谁知道我的问题是什么?

编辑:

添加了animate方法的代码:

func animate(toValue: Double) {
    let animation = CABasicAnimation(keyPath: "strokeEnd")

    animation.duration = 1.0
    animation.fromValue = 0
    animation.toValue = toValue

    topProgressBar.strokeEnd = CGFloat(toValue)
    topProgressBar.animation(forKey: "animate")
}

2 个答案:

答案 0 :(得分:2)

问题始于var progressBar = ProgressBar()。这将调用init方法并调用configure()。此时ProgressBar框架宽度和高度为zero

configure()方法中,您正在设置线宽。

bottomProgressBar.lineWidth = self.frame.height // 0
topProgressBar.lineWidth = self.frame.height // 0

因此行宽设置为zero,这样就不会显示。

要解决此问题,您必须使用CAShapeLayer方法更新layoutSubviews()行宽。

override func layoutSubviews() {
    super.layoutSubviews()

    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addLine(to: CGPoint(x: self.frame.width, y: 0))

    bottomProgressBar.lineWidth = self.frame.height // Update lineWidth
    topProgressBar.lineWidth = self.frame.height    // Update lineWidth

    bottomProgressBar.path = path.cgPath
    topProgressBar.path = path.cgPath
}

为什么它适用于故事板?因为在configure被调用之前已经设置了帧。您可以在configure中打印帧大小,并查看两种方案中的差异。

答案 1 :(得分:0)

自定义视图的显示始终存在错误,您可以将其添加到viewDidLoad

 self.progressBar.setNeedsDisplay()

编辑:

您可以添加此行以配置视图的方法默认背景颜色,因为默认为透明

 self.backgroundColor = UIColor.red

我看到所有颜色都是白色的,所以通常不会看到任何颜色