iOS初級開發學習筆記:一個頁面中自動計算cell的高度來自適應tableView的高度

蘆葦科技App技術團隊發表於2019-02-15

專案中有一個頁面為活動詳情頁,其中活動的相關內容放置於一個底色為白色的view中,其他的背景色為灰色。效果完成圖如下

iOS初級開發學習筆記:一個頁面中自動計算cell的高度來自適應tableView的高度

因為內容分為活動時間、金額、規則等且有橫線隔開,所以決定用 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];
        }
    }];
複製程式碼

這裡再貼一遍最終效果:

iOS初級開發學習筆記:一個頁面中自動計算cell的高度來自適應tableView的高度

一些細節:

活動詳情內容,需要給一個最大寬度,考慮適配,應該計算,而不是給確定值,這裡例子為(左側例如“挑戰時間”這些title我是給了控制元件寬度的,計算時要減去):

//自動換行
_detailLabel.numberOfLines = 0;
//31、33為左右邊距,67為左側title長度
_detailLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 31-33 - 67;
複製程式碼

作者介紹

  • 李鴻:廣州蘆葦科技 APP 團隊 iOS 開發工程師

內推資訊

  • 我們正在招募小夥伴,有興趣的小夥伴可以把簡歷發到 app@talkmoney.cn,備註:來自掘金社群
  • 詳情可以戳這裡--> 廣州蘆葦資訊科技

相關文章