简单的基于组合的Custom View 示例 - 一个前面带一个 Icon 的 TextField的简单实现
需求
一个项目中很多地方都用到这种一个Icon 后面跟着一个TextField的 UI. 因为 Xcode 不支持这种界面上的重用.
而且就是是Copy and Paste也是有问题的,因为Copy进,View的约束并不会跟着走
为了避免重复劳动 ,就只要写一个简单的Custom View来实现了.
代码分析:
完整源代码见: https://gist.github.com/banxi1988/d31c7a41f29e7ddca728
-
@IBDesignable- 自定义View的类声明没有此属性的话,Interface Builder 中的预览界面是显示不出来的. - 可以通过
prepareForInterfaceBuilder()方法来设置,只在开发时可用的初始值, 注意在开发时的,资源加载需要多写的代码.如:
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
let bundle = NSBundle(forClass: self.dynamicType)
let image = UIImage(named: "icon_locate", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
iconImageView.image = image
textField.text = "大学英语四级"
backgroundColor = UIColor.lightGrayColor()
}
- 注意重写
instrinsicContentSize()一般的实现逻辑的,遍历,组合,比较,求和.
override func intrinsicContentSize() -> CGSize {
let iconSize = iconImageView.intrinsicContentSize()
let textSize = textField.intrinsicContentSize()
let width = padding.left + iconSize.width + iconPadding + textSize.width + padding.right
let height = padding.top + max(iconSize.height, textSize.height) + padding.bottom
return CGSize(width: width, height: height)
}
设置AutoLayout约束时,值得注意:
4.1 除非确实需要,不要忘记调用iconImageView.setTranslatesAutoresizingMaskIntoConstraints(false)
4.2 设置好contentHuggingPriority,和 contentResistancePriority
如这里,在整个UI控制伸长时,先让textField变长
textField.setContentHuggingPriority(240, forAxis: UILayoutConstraintAxis.Horizontal)当组合中的子控件的内容发生了变化,正确做法是应该调用:
invalidateIntrinsicContentSize()@IBInspectable属性目前不建议使用,用一次卡一次
如果取消不用了,记得将IB中控件属性的这些自定义属性,删除.
PS:
问: 标题是基于组合的Custom View 那还有基于其他的吗?
答: 有,还有基于继承,然后主要是 自定义 drawRect 方法,或者自定义 CALayer的
当然,更多是两者都基于.
希望对大家有用.