我们有一个使用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
}
}
答案 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
}
}