在日常開發(fā)中传蹈,一個(gè)App會(huì)有很多模塊中的小模塊相差不多兴猩。這時(shí)候我們就需要考慮公用 -- 自定義View 鞭衩, 這樣就可以避免很多重復(fù)的代碼敲茄。
有哪些需要考慮的
- 首先要考慮不同的調(diào)用充包,純代碼的方式或者Xib 秕岛、Storyboard的方式都要可以使用
- 要有一定的可定制化 ,也就是暴露出來(lái)的屬性
- 使用起來(lái)簡(jiǎn)單
實(shí)例
例如有這樣的 View
在不同的地方有用到误证。
很簡(jiǎn)單的一個(gè)視圖继薛,圖片加文字加邊框。
首先愈捅,新建一個(gè)UIView
的子類ImageTextView
, 在class前面添加open
關(guān)鍵字 (我們要做成公用的)
刪除drawRect相關(guān)方法遏考,將下面代碼復(fù)制進(jìn)去
public override init(frame: CGRect) {
super.init(frame: frame)
#if !TARGET_INTERFACE_BUILDER // 非interfabuilder環(huán)境下
// 如果是從代碼層面開始使用Autolayout,需要對(duì)使用的View的translatesAutoresizingMaskIntoConstraints的屬性設(shè)置為false
translatesAutoresizingMaskIntoConstraints = false
#endif
prepareView()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepareView()
}
// 布局
func prepareView(){
}
init?(coder:)
是從Xib或者Storyboard創(chuàng)建的時(shí)候會(huì)調(diào)用。 其他看注釋咯 - _ -
為UIImageView
添加一個(gè)擴(kuò)展,方便創(chuàng)建UIImageView
對(duì)象
extension UIImageView {
class func configuredImageView() -> UIImageView {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.clipsToBounds = true
imageView.contentMode = .scaleAspectFill
return imageView
}
}
回到ImageTextView
中聲明圖片和文本的變量
fileprivate let imageView = UIImageView.configuredImageView()
fileprivate lazy var textLabel = UILabel()
在prepareView
中對(duì)圖片和文本進(jìn)行布局
// 布局
func prepareView(){
textLabel.translatesAutoresizingMaskIntoConstraints = false
textLabel.font = UIFont.systemFont(ofSize: CGFloat(textSize))
addSubview(imageView)
addSubview(textLabel)
imageView.setContentCompressionResistancePriority(1000, for: .horizontal )
NSLayoutConstraint.activate([
imageView.leftAnchor.constraint(equalTo: leftAnchor, constant:10 ) ,
imageView.centerYAnchor.constraint(equalTo: centerYAnchor) ,
textLabel.leftAnchor.constraint(equalTo: imageView.rightAnchor , constant:2 ) ,
textLabel.centerYAnchor.constraint(equalTo: centerYAnchor) ,
textLabel.rightAnchor.constraint(equalTo: rightAnchor, constant:-10)
])
layer.borderColor = UIColor.lightGray.cgColor
layer.borderWidth = 0.5
layer.cornerRadius = 3
}
這里的布局方法是iOS 9 開始支持的API 蓝谨, 當(dāng)然你也可以使用SnapKit
為了使我們的View
可以在 InterfaceBuilder
中使用灌具,在類前面使用注解 @IBDesignable
并暴露出可以自定義的屬性
extension ImageTextView{
@IBInspectable
open var image:UIImage?{
get{
return imageView.image
}
set{
imageView.image = newValue
}
}
@IBInspectable
open var text:String?{
get{
return textLabel.text
}
set{
textLabel.text = newValue ?? ""
}
}
@IBInspectable
open var textColor:UIColor? {
get{
return textLabel.textColor
}
set{
textLabel.textColor = newValue
}
}
}
在變量聲明下面在加上字體大小
// 這里使用 textSize 是因?yàn)?IBInspectable 暫時(shí)還不支持 UIFont
@IBInspectable
open var textSize:UInt = 17 {
didSet{
textLabel.font = UIFont.systemFont(ofSize: CGFloat(textSize))
}
}
這塊由于暫時(shí)不支持UIFont
所以使用了UInt
我們還可以在InterfaceBuilder
渲染前做一些事情
override open func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
// interface builder 渲染前執(zhí)行 不會(huì)影響真正運(yùn)行效果
layer.borderColor = UIColor.lightGray.cgColor
layer.borderWidth = 0.5
layer.cornerRadius = 3
}
到這里青团,這個(gè)自定義View
就算完成了,看下載Storyboard中的使用吧
隨便拖一個(gè)UIView
修改Class屬性
保存后就可以看到這些屬性了
設(shè)置完成后 InterfaceBuilder
立刻會(huì)渲染出來(lái)
這里是我隨便設(shè)了幾個(gè)屬性
有了這個(gè)自定義的View
咖楣,那么在任何地方有相似效果督笆,我們只需要像拖UILabel
一樣把他拖出來(lái)簡(jiǎn)單的設(shè)置下屬性就好了(也可以通過(guò)手寫代碼創(chuàng)建)。當(dāng)然诱贿,這只是一個(gè)簡(jiǎn)單的demo娃肿,并沒有涉及到事件Layer以及動(dòng)畫等,如果有興趣下次再講珠十。