仅在首次初始化自定义UIView

时间:2019-08-28 07:43:10

标签: ios swift iphone uiview layoutsubviews

我们有一个使用Interface Builder中的约束的自定义UIView,并且我们已经修改了该视图以使其具有需要绘制的自定义形状。

形状的大小取决于在Interface Builder中应用于此自定义视图的约束,因此,为了以合适的大小在自定义UIView中获得形状,我们需要在LayoutSubviews中对其进行调用。

问题是,当在屏幕方向定向期间调用LayoutSubviews时,由于在自定义UIView的设置函数中调用了另一个形状,因此该形状又添加到了屏幕上。

可以通过添加一个布尔值来解决此问题,该布尔值确定是否是第一次调用LayoutSubviews,并且只有在第一次调用LayoutSubviews时,才将形状层添加到视图中。

我在这里和网络上进行了一些研究,发现了一篇有关如何通过不同方法实现所描述行为的文章。

https://thomasclowes.com/ios-when-to-layout-your-views/

作者提到了一个自定义类BaseView和可以实现此行为的协议。

解决方案写在“ UIView和layoutSubviews”下。

我正在努力了解解决方案,并想知道是否有人可以澄清并显示有关如何实现本文中提到的解决方案的代码示例。

谢谢。

class CustomView: UIView {

    private var firstTimeInit = true

    override func layoutSubviews() {
        super.layoutSubviews()

        setup()
    }

    private func setup() {

        // Check if the the method was already executed
        if firstTimeInit == false { return }

        let label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 21))
        label.font = UIFont.systemFont(ofSize: 13, weight: .bold)
        label.text = "Daily"
        label.textAlignment = .center
        label.sizeToFit()
        addSubview(label)
        label.center.x = bounds.midX

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

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = shapePath.cgPath
        shapeLayer.strokeColor = UIColor(hex: 0xD5E5EF).cgColor
        shapeLayer.lineWidth = 3
        shapeLayer.lineCap = .round
        shapeLayer.position.y = frame.height / 2
        shapeLayer.lineDashPattern = [frame.width / 2.5, frame.width / 5, frame.width / 2.5] as [NSNumber]
        layer.addSublayer(shapeLayer)

        firstTimeInit = false
    }
}

2 个答案:

答案 0 :(得分:1)

为什么不一次创建predict(w , b, X[0]) ValueError: shapes (6,4) and (6,) not aligned: 4 (dim 1) != 6 (dim 0) ,将其添加到构造函数的子视图中,然后仅使用UILabel重新计算其框架或图案?

赞:

CAShapeLayer

通过这种方式,您的自定义形状将适应layoutSubviews的变化,而不会重复自身。

很明显,如果您使用class CustomView: UIView { private let label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 21)) private let shapeLayer = CAShapeLayer() override init(frame: CGRect) { super.init(frame: frame) label.font = UIFont.systemFont(ofSize: 13, weight: .bold) label.text = "Daily" label.textAlignment = .center addSubview(label) shapeLayer.strokeColor = UIColor(hex: 0xD5E5EF).cgColor shapeLayer.lineWidth = 3 shapeLayer.lineCap = .round layer.addSublayer(shapeLayer) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func layoutSubviews() { super.layoutSubviews() label.sizeToFit() label.center.x = bounds.midX let shapePath = UIBezierPath() shapePath.move(to: CGPoint(x: 0, y: 0)) shapePath.addLine(to: CGPoint(x: frame.width, y: 0)) shapeLayer.path = shapePath.cgPath shapeLayer.position.y = frame.height / 2 shapeLayer.lineDashPattern = [frame.width / 2.5, frame.width / 5, frame.width / 2.5] as [NSNumber] } } ,则可能需要实际实现。

答案 1 :(得分:0)

一种方法是在自定义视图中使用didSet方法。例如

class CustomView: UIView {

    var firstTimeInit : Bool = false {
        didSet {
            layoutSubviews()
        }
    }


    override func layoutSubviews() {
        super.layoutSubviews()
        // i am only changing the color to check if the layoutSubview is called. 
        // i have a viewController in storyboard with a UIView Background Color set to gray. 
        backgroundColor = UIColor.red
    }

}

要使用该方法,请确保在自定义视图中调用了didSet方法,您可以在将要加载自定义视图的视图控制器的viewdidLoad函数中使用它。

class ViewController: UIViewController {

    let customView = CustomView()

    override func viewDidLoad() {
        super.viewDidLoad()
        customView.viewDidSet = true
    }
}