基本声命周期
1 初始化 -》 2 约束和布局 -〉 3绘制渲染 -》 4 销毁
init(coder:)/init(frame:) // 【初始化】可视化加载/代码初始化
init(frme: CGRect): 代码初始化时调用。
init(coder: NSCoder): xib 或者 stroryboard 加载时调用。
updateConstraints() // 【约束更新】可选, 基于 AutoLayout 布局时调用
layoutSubviews() // 【子视图布局】调用一次或者多次,基于 AutoLayout 一般会调用两次及以上
draw(_:) // 【绘制】
draw(_:in:)
布局约束周期
1 基于frame坐标系布局的,在layoutSubViews方法中设置frame。
2 不建议在updateConstraints() 里添加约束,建议在动作发生时修改约束值,而不是在该方法。
3 Auto layout 的布局过程是 updateConstraints -》 layoutSubViews -〉 draw ,这三步不是单向的。如果layout 的过程中改变了constrait ,会触发update constraints,进行新一轮的迭代。
// 重点: 重写updateConstraints() 一定要在最后调用super.updateConstraints()
1 纯代码自定义View
// 代码初始化
override init(frame: CGRect) { super.init(frame: frame) commonInit() }
// 用在xib 和 storyboard 初始化
required init?(coder: NSCoder) { super.init(coder: coder) commonInit() }
添加 View 和设置控件
fileprivate func commonInit() {
addSubview(imageView) // 没有设置frame 大小
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 14)
label.textColor = .green
addSubview(label) // 没有设置frame大小
}
2 布局子控件
重写layouSubviews()并设置子控件位置大小
override func layoutSubviews() {
super.layoutSubviews()
let imageViewW: CGFloat = 60
let imageViewX = (bounds.width-60)/2
imageView.frame = CGRect(x: imageViewX, y: 8,width: imageViewW, height: imageViewW)
let labelY = imageViewW + 8 + 8
label.frame = CGRect(x: 0, y: labelY, width: bounds.width, height: 17)
}
2 自定义 XIB UIView
代码如下:
class CustomXibView: UIView {
var contentView:UIView!
class func instantiateFromNib() -> CustomXibView {
returnBundle.main.loadNibNamed("CustomXibView", owner:nil, options:nil)?.firstas!CustomXibView
}
//初始化时将xib中的view添加进来
overrideinit(frame:CGRect) {
super.init(frame: frame)
contentView = CustomXibView.instantiateFromNib()
initialSetup()
}
//初始化时将xib中的view添加进来
requiredinit?(coder aDecoder:NSCoder) {
super.init(coder: aDecoder)
contentView = CustomXibView.instantiateFromNib()
initialSetup()
}
//用约束在xib里设置frame
// 1 Controller->loadView ,Controller->viewDidLoad 两个方法后调用
// 2 初始化时没有设置rect,不被自动调用。
// 3 控制器设置值给View
// 4 设置contentMode为UIViewContentModeRedraw,每次设置或更改frame时候调用draw
// 5 直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
overridefuncdraw(_rect:CGRect) {
super.draw(rect)
//设置一些子视图的固定属性
}
//初始化默认属性配置
func initialSetup(){
//值的属性
}
//布局相关设置
// 1、init初始化不会触发layoutSubviews。
// 2、addSubview会触发layoutSubviews。
// 3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
// 4、滚动一个UIScrollView会触发layoutSubviews。
// 5、旋转Screen会触发父UIView上的layoutSubviews事件。
// 6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
// 7、直接调用setLayoutSubviews。
override func layoutSubviews() {
super.layoutSubviews()
// 布局相关的一些设置
}
/* 当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的 awakeFromNib函数来响应这个消息,执行一些必要的操作。也就是说通过nib文件创建view对象是执行awakeFromNib 先init 再awakeFromNib()(一般做初始化操作)。*/
override func awakeFromNib() {
super.awakeFromNib()
}
}
// 外部调用
let xibView = CustomXibView.instantiateFromNib()
xibView.frame=CGRect(x:10, y:30, width:200, height:40)
self.view.addSubview(xibView)
纯代码
overrideinit(frame:CGRect)
requiredinit?(coder aDecoder:NSCoder)
纯xib
awakeFromNib()
网友评论