UIView
相當(dāng)于一個<div>
, 自定義UIView
, 其實就是寫一個組件索抓,向里面添加一些子UIView
, 并自動響應(yīng)事件抒和,刷新布局崇决。
自定義UIVIew
其實就是把自己做為一個容器啦扬,進(jìn)行組合其它的標(biāo)簽形成的一個多元結(jié)構(gòu)
也不排除使用繪圖功能來創(chuàng)建自繪組件互例。
一吓妆、最重要的生命周期鉤子 layoutSubviews
layoutSubviews
的意義在于需要的時候重新調(diào)整子uiview
的布局鹅心, 來響應(yīng)根view
的大小變化储狭。
記得一定要調(diào)用父組件的[super layoutSubviews]
, 因為可能父類不一定是uiview
這個空組件。
這個鉤子的意義在于更新子組件的大小與位置释移,與子組件的其它屬性關(guān)系不大叭披,除非強(qiáng)制要關(guān)聯(lián)一些與大小相關(guān)的響應(yīng),其實這個鉤子就是手動約束子元素的空間屬性玩讳。
那么什么時候會觸發(fā)這個鉤子呢?
- 手動調(diào)用組件的
[self setNeedsLayout]
的時候趋观,強(qiáng)制重新調(diào)整內(nèi)容布局扛禽。 - 添加子元素
addSubview
的時候,因為內(nèi)容變化了皱坛,系統(tǒng)認(rèn)為要自動觸發(fā)一次编曼。 - 組件
frame
任何一個分量變化的時候,子元素必須響應(yīng)剩辟,所以也會調(diào)用一次掐场,但記住使用為 0x0的時候可能不會觸發(fā),系統(tǒng)認(rèn)為這個時候不可見贩猎,不用觸發(fā)熊户。約束會自動調(diào)整frame,所以也會進(jìn)入吭服。 - 滾動
UIScrollViwe
的時候嚷堡,因為可能有一些懸停效果fixed
, 所以也會進(jìn)入到這里面。 - 旋轉(zhuǎn)屏幕可能會進(jìn)入艇棕,
二蝌戒、UILabel 的自適應(yīng)大小
在布局
UILable
的時候,我們總得知道這個元素的大小沼琉。
要知道一個標(biāo)簽應(yīng)該的大小北苟,首先要置入一個虛擬容器中,這樣才有可能算出充滿容器時應(yīng)該的大小打瘪。
計算方法有兩類
1友鼻、 NSString
的方法。
sizeWithFont 這個方法已棄用在
iOS7
的時候使用更強(qiáng)大的屬性文本大小計算
這個貌似只能算單行的大小闺骚。
CGSize size = [self.statusLabel.text sizeWithAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:12.0f]}];
CGSize statuseStrSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
- 還有文本邊框矩形計算方法彩扔, 注意返回的是一個
CGRect
。
還要注意屬性要和標(biāo)簽本身的屬性一樣僻爽,比如字體大小借杰,否則會算出來會有偏差
算出來的是一個小數(shù),要用 ceil 方法向上取整进泼。
CGRect rect = [textToMeasure boundingRectWithSize:CGSizeMake(width, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
2、 UILabel
的方法, 內(nèi)部應(yīng)該是使用上面的方法來實現(xiàn)的纤虽。
-
sizeThatFits
, 這個方法應(yīng)該是邊框計算方法乳绕,內(nèi)部調(diào)用boundingRectWithSize
實現(xiàn)
CGSize suggestedSize = [lb sizeThatFits:CGSizeMake(200, 30)];
-
[label sizeToFit]
, sizeToFit會自動調(diào)用sizeThatFits方法;
它不返回值逼纸,直接把大小應(yīng)該到標(biāo)簽本身洋措。
二、UIImageView
的自適應(yīng)大小
一般指的是網(wǎng)絡(luò)圖片杰刽, 假如事先不知道圖片的大小(除非服務(wù)器返回圖片大小)菠发,無法去設(shè)置容器的大小王滤,只能在圖片加載回來后,再進(jìn)行調(diào)整滓鸠,調(diào)用
setNeedsLayout
進(jìn)行再次進(jìn)入layoutSubviews
布局雁乡。
一般使用第三方組件比如 SDWebImage
來加載圖片,在回調(diào)中拿到大小再進(jìn)行設(shè)置糜俗。
三踱稍、組件結(jié)構(gòu)劃分
一個組件除了 layout
布局,還有種狀態(tài)悠抹、外觀修飾珠月,記得凡是修改了子組件的布局相關(guān)的屬性,都記得要手動去刷新重新計算布局楔敌。
四啤挎、使用圖形接口繪制容器本身
建議使用
CALayer
來實現(xiàn)自繪控件,而不要使用drawRect
卵凑,drawRect
會創(chuàng)建一個臨時圖像去存儲繪制內(nèi)容庆聘。
DrawRect
:DrawRect
屬于CoreGraphic
框架,占用CPU氛谜,消耗性能大, 引起內(nèi)存暴增掏觉。
CAShapeLayer
:CAShapeLayer
屬于CoreAnimation
框架,通過GPU來渲染圖形值漫,節(jié)省性能澳腹。動畫渲染直接提交給手機(jī)GPU,不消耗內(nèi)存杨何。