項目中有一個頁面爲活動詳情頁,其中活動的相關內容放置於一個底色爲白色的view中,其餘的背景色爲灰色。效果完成圖以下數組
由於內容分爲活動時間、金額、規則等且有橫線隔開,因此決定用 tableview 來畫,建立一個 cell 文件添加內容,再建立一個 controller 在內建立 tableview 承載便可。bash
內容因爲分類不一樣放置於各個 cell 中。然而其中文字內容長度均不一樣且在後續使用中一定會改變。 cell 的高度根據內容自適應由app
//row高自適應
_tableView.rowHeight = UITableViewAutomaticDimension;
//給一個預估值,當計算不出時會默認使用此高度
_tableView.estimatedRowHeight = 100;
複製代碼
便可設置。佈局
先這樣想:計算每個 cell 的高度,再把它們各自高度的值傳至 controller 中進行累加。ui
首先須要傳值,選擇用 ReactiveObjc(即RAC) 來進行傳值:atom
在 cell.h 中聲明 subject :spa
@property (nonatomic, strong) RACSubject *subject;
複製代碼
cell.m 中懶加載建立:代理
- (RACSubject *)subject{
if (!_subject) {
_subject = [RACSubject subject];
}
return _subject;
}
複製代碼
在建立 cell 的代理中的語句code
ABLaborActivityDetailViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
複製代碼
一開始,在 cell.m 中的 setLayout 佈局方法中,是先走一遍及局,建立控件的,在執行至 cell.index = indexPath.row; 時,纔會走 setIndex 方法,給控件內容賦值。cdn
因此要確認什麼時候開始傳值,咱們要聲明一個全局變量
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 內代碼也結束啦
須要建立全局變量接收傳過來的 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;
//3一、33爲左右邊距,67爲左側title長度
_detailLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 31-33 - 67;
複製代碼
- 李鴻:廣州蘆葦科技 APP 團隊 iOS 開發工程師
- 咱們正在招募小夥伴,有興趣的小夥伴能夠把簡歷發到 app@talkmoney.cn,備註:來自掘金社區
- 詳情能夠戳這裏--> 廣州蘆葦信息科技