程式碼部分 : https://github.com/ZhaoBingDong/CAAnimaiton
一 sizeThatFits 和 sizeToFit的區別
UIView 有個 sizeToFit 方法來計算 UIView 合適的 bounds.size, 注意 autolayout 約束過的 view 該方法失效.
- (void)sizeToFit;
// calls sizeThatFits: with current view bounds and changes bounds size.
呼叫這個方法會改變當前 view 的 bounds.size
複製程式碼
- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size
// 意思大概是 返回“最佳”大小適合給定的大小 預設返回已經存在的檢視 size
複製程式碼
當一個 view 例如 label 設定完 text 屬性後 呼叫[label sizeToFit]; 會根據 label 內容計算出合適的 size 來完全顯示 label 內容
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 100.0f, 0.0f, 0.0f)];
label1.backgroundColor = [UIColor yellowColor];
label1.text = @"當一個 view 例如 label 設定完 text 屬性後 呼叫[label sizeToFit]; 會根據 label 內容計算出合適的 size 來完全顯示 label 內容";
label1.numberOfLines = 0;
[label1 sizeToFit];
[self.view addSubview:label1];
複製程式碼
上邊的方法 如果不設定 label 的 frame.size.with 那麼 label 會自適應寬度 而不會改變它的高度,所以 label 雖然設定了 numberOfLines = 0 ,依然無法換行 .大部分應用當文字一行顯示不完全時需要給 label 換行,那麼就要限定 label 的 maxWidth
還是同樣的程式碼 由於我指定了 label 的 width = 100.0f ,在 [label sizeToFit] 會發現 label 的最大 with =100 顯示不完全部分換行 高度自適應.
所以 sizeToFit 並不能夠完全按我們設想的哪樣去自適應 label 的 bounds.size
那麼 sizeToFit 內部到底做了哪些操作呢?
其實當呼叫 UIView 的 sizeToFit 後 會呼叫 sizeThatFits 方法來計算 UIView 的 bounds.size 然後改變 frame.size
UIView 的 - (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = [super sizeThatFits:size];
NSLog(@"size =%@",NSStringFromCGSize(newSize));
return newSize;
}
不妨將上邊程式碼部分發 UILabel 改成子類化的 MyLabel 重寫sizeThatFits 列印出 newSize ={99, 223.5}
複製程式碼
其實我們也可以不使用 [ label sizeToFit] 來計算 label 內容的 size ,首先呼叫 sizeThatFits 方法或者一個 CGSize 然後改變 label.frame.size 就可以得到 [label sizeToFit]一樣的效果
// 或者給一個限定的寬度和高度 讓 label 在這個範圍內進行自適應 size
CGSize labelSize = [label1 sizeThatFits:CGSizeMake([[UIScreen mainScreen] bounds].size.width, MAXFLOAT)];
CGRect rect = CGRectMake(label1.frame.origin.x, label1.frame.origin.y, labelSize.width, labelSize.height);
[label1 setFrame:rect];
複製程式碼
由此可見 sizeThatFits 比 sizeToFit 更加靈活的設定一個自適應size 的 view , 可以定製 label 計算內部內容的規則
下邊是重寫子類 sizeThatFits 自定義的一個 計算label siztToFit 後改變 frame.size 的方法
- (void)layoutSubviews
{
[super layoutSubviews];
_label1.frame = CGRectMake(_margin, _margin, _cacheSize1.width, _cacheSize1.height);
_label2.frame = CGRectMake(_margin, CGRectGetMaxY(_label1.frame) + _margin, _cacheSize2.width, _cacheSize2.height);
}
- (CGSize)sizeThatFits:(CGSize)size
{
CGFloat w = size.width;
w -= 2 * _margin;
_cacheSize1 = [_label1 sizeThatFits:CGSizeMake(w, MAXFLOAT)];
_cacheSize2 = [_label2 sizeThatFits:CGSizeMake(w, MAXFLOAT)];
CGFloat h = 3 * _margin + _cacheSize1.height + _cacheSize2.height;
return CGSizeMake(size.width, h);
}
複製程式碼
當你呼叫 自定義 View 的 sizeToFit 方法後 會根據自定義的 sizeThatFits:(CGSize)size 規則來計算 label 來改變 label 完全內容的 size
TestSizeFit *customerView = [[TestSizeFit alloc] init];
[customerView setLabel1Text:@"大兵布萊恩特" setLabel2Text:@"巴爺科技 (上海) 有限公司"];
[customerView sizeToFit];
[self.view addSubview:customerView];
複製程式碼
通過上邊的程式碼示例 可以知道 sizeToFit 方法背後怎麼實現的 , sizeThatFits 可以子類化重寫自己的計算規則
好了,我是大兵布萊恩特,歡迎加入博主技術交流群,iOS 開發交流群