專案中有一個頁面為活動詳情頁,其中活動的相關內容放置於一個底色為白色的view中,其他的背景色為灰色。效果完成圖如下
因為內容分為活動時間、金額、規則等且有橫線隔開,所以決定用 tableview 來畫,建立一個 cell 檔案新增內容,再建立一個 controller 在內建立 tableview 承載即可。
內容由於分類不同放置於各個 cell 中。然而其中文字內容長度均不同且在後續使用中必定會改變。 cell 的高度根據內容自適應由
//row高自適應
_tableView.rowHeight = UITableViewAutomaticDimension;
//給一個預估值,當計算不出時會預設使用此高度
_tableView.estimatedRowHeight = 100;
複製程式碼
即可設定。
而 tableview 的高度要根據各 cell 高度來計算累加該怎麼做呢?
先這樣想:計算每一個 cell 的高度,再把它們各自高度的值傳至 controller 中進行累加。
首先需要傳值,選擇用 ReactiveObjc(即RAC) 來進行傳值:
在 cell.h 中宣告 subject :
@property (nonatomic, strong) RACSubject *subject;
複製程式碼
cell.m 中懶載入建立:
- (RACSubject *)subject{
if (!_subject) {
_subject = [RACSubject subject];
}
return _subject;
}
複製程式碼
在建立 cell 的代理中的語句
ABLaborActivityDetailViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
複製程式碼
一開始,在 cell.m 中的 setLayout 佈局方法中,是先走一遍佈局,建立控制元件的,在執行至 cell.index = indexPath.row; 時,才會走 setIndex 方法,給控制元件內容賦值。
所以要確認何時開始傳值,我們要宣告一個全域性變數
BOOL _isLayout;//狀態開關
複製程式碼
並在佈局方法 - (void)setLayout 中一開始令初始狀態為 NO
_isLayout = NO;
複製程式碼
在 setIndex 賦值方法中:
- (void)setIndex:(NSInteger)index{
self.titleLabel.text = self.dataArray[index][@"title"];
self.detailLabel.text = self.dataArray[index][@"detail"];
//通過 index 和陣列給 cell 內容賦值時,讓開關為 YES ,走幾次由我們建立的陣列決定,每一次都會走 layoutIfNeeded 方法。
_isLayout = YES;
//呼叫 layoutSubviews 方法
[self layoutIfNeeded];
}
複製程式碼
也就是走完一次 setLayout 建立空控制元件後,讓 _isLayout = YES;
此時才開始傳值,此方法新增在 setLayout 方法末尾:
- (void)layoutSubviews{
[super layoutSubviews];
//每次訊號為 YES ,都會通過 RAC 傳出 cell 的高度 self.size.height 。
if (_isLayout == YES) {
[self.subject sendNext:@(self.size.height)];
//列印 cell高檢查
NSLog(@"CELL高=%f",self.size.height);
}
複製程式碼
執行結果列印 cell 高如下,前10行,均為計算空控制元件賦值前的初始高度(44)-> 得到內容後的高度,迴圈5次(因為有5個 cell ),後5行即各cell最終高度。
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=44.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=44.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=44.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=44.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=81.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=44.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=96.500000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=50.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=81.000000
function:-[ABLaborActivityDetailViewCell layoutSubviews] line:82 content:CELL高=96.500000
複製程式碼
這樣在 cell 內傳值結束, cell 內程式碼也結束啦
到對應的 controller 中:
需要建立全域性變數接收傳過來的 cell 高:
{
CGFloat _tableViewHeight;//接收cell的高度
BOOL _isEnd;//重新整理開關
}
複製程式碼
這裡有個 BOOL 變數,因為在接收值重新整理 tableview 的時候,會出現死迴圈,為了解決死迴圈,需給一個開關進行判斷何時重新整理停止。
在 viewDidLoad 中給兩個全域性變數以初始狀態:
_tableViewHeight = 0;//給初始高度
_isEnd = NO;//給初始狀態
複製程式碼
在 cell 內容代理中:
weakifyySelf;
[cell.subject subscribeNext:^(NSNumber *x) {
stronggSelf;
//接收cell值並累加
_tableViewHeight = _tableViewHeight + [x floatValue];
//在進行到第5行時,並且開關處於 NO 狀態,則執行開關切換為YES,防止再次重新整理;給 tableview 範圍,
並重新整理資料,令其顯示正確範圍,高度計算完畢需按實際情況進行調整,這裡 +50 使顯示完全
if (indexPath.row == 4 && _isEnd == NO) {
_isEnd = YES;
self.tableView.size = CGSizeMake(SCREEN_WIDTH - 30, _tableViewHeight+50);
[self.tableView reloadData];
}
}];
複製程式碼
這裡再貼一遍最終效果:
一些細節:
活動詳情內容,需要給一個最大寬度,考慮適配,應該計算,而不是給確定值,這裡例子為(左側例如“挑戰時間”這些title我是給了控制元件寬度的,計算時要減去):
//自動換行
_detailLabel.numberOfLines = 0;
//31、33為左右邊距,67為左側title長度
_detailLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 31-33 - 67;
複製程式碼
作者介紹
- 李鴻:廣州蘆葦科技 APP 團隊 iOS 開發工程師
內推資訊
- 我們正在招募小夥伴,有興趣的小夥伴可以把簡歷發到 app@talkmoney.cn,備註:來自掘金社群
- 詳情可以戳這裡--> 廣州蘆葦資訊科技