1. 程式人生 > >使用autolayout自定義動態高度的cell

使用autolayout自定義動態高度的cell

關於使用autolayout建立動態cell,網上也有不少的文章,但是裡面的內容都是說的一個問題,簡稱換湯不換藥,都是說的一些UILabel或者UITextView等等一些控制元件顯示的文字內容不同來實現不同的高度。

但是我們平常使用的自定義cell很多都是顯示不同數量的控制元件,來顯示不同的高度,比如微博首頁,餓了麼首頁那些cell,都是下面顯示不同數量的控制元件來顯示不同高度的cell,那麼下面就讓我們一起看看怎麼使用autolayout實現這種自定義cell

關於使用autolayout實現cell動態高度有兩種實現方式

iOS8以後
iOS8以後比較爽:只需要設定下面兩句程式碼就行了

//設定cell的估計高度
self.tableView.estimatedRowHeight = 200;

//iOS以後這句話是預設的,所以可以省略這句話
self.tableView.rowHeight = UITableViewAutomaticDimension;

你可能沒有看到實現代理方法返回cell高度。明確告訴你iOS8以後不需要實現了,系統會自動推斷出cell的高度。

but,iOS7還是需要

下面就是iOS7實現的方式,還是需要實現這個方法,iOS8那兩句程式碼不寫也可以

//如果要支援iOS7這個方法必須實現
-(CGFloat)tableView:(UITableView
*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //其他程式碼 //自動算高度,+1的原因是因為contentView的高度要比cell的高度小1 CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1; return height; }

主要就是下面這句程式碼,能自動計算出contentView的高度和寬度

CGFloat height = [cell.contentView
systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;

上面這兩種方式可以一起存在,既支援ios7也支援iOS8.

開始demo

先來看一下我們最終的效果:
效果圖

  • 有的cell只有一個UITextLabel,並且label會根據內容的多少來改變高度
  • 有的cell下面還有一個UIButton,並且cell會根據有沒有button來動態改變高度

實現思路
- 首先自定義一個cell,順便建立一個xib檔案
- 在xib檔案中把所有包含的控制元件全部搞上去,設定好約束
- 如果不需要哪個控制元件顯示就把哪個控制元件的高約束設定為0
- 如果需要顯示哪個控制元件就保證這個控制元件沒有高度約束(應該容易想的到因為是動態高度的cell,所以不能有高度的約束)
- 然後更新約束,顯示cell

在這裡我們使用xib的方式建立自定義cell

如圖:

這裡設定約束有幾個注意點

  • 每一個控制元件都只設置上下左右的約束,不設定寬高的約束,有些必須要固定大小的可以設定一下
  • 有些控制元件如果不設定寬高xib會報錯的話,就設定佔位符placehoder
  • 像一些要消失或者顯示的控制元件,最好設定他與其他顯示的控制元件間距為0

這是我自定義cell的類

在控制器中我們實現資料來源程式碼

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCell" bundle:nil] forCellReuseIdentifier:@"cell"];

    self.tableView.allowsSelection = NO;

    //胡亂寫的,為了懶省事,大家湊合著看吧
    self.tableData = @[@"1\n2\n3\n4\n5\n6", @"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3\n4\n5\n6", @"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3",@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"@"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"123456789012345678901234567890", @"1\n2\n3",@"1\n2\n3"];
}


-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.tableData.count;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

    cell.text = self.tableData[indexPath.row];

    return cell;
}

我們先使用iOS8的方法
接下來就是去自定義cell類(MyTableView.m)中重寫-updateConstraints 方法

-(void)updateConstraints {
    //remove Constraints
    [self.height uninstall];

    //add Constraints
    [self.content mas_makeConstraints:^(MASConstraintMaker *make) {
       self.height = make.height.equalTo(@60);//any number
    }];

    if(self.isShowView == NO) {
        //change Height Constrains to be 0
        [self.content mas_updateConstraints:^(MASConstraintMaker *make) {
            make.height.equalTo(@0);
        }];
    }
    else {
        //remove Constraints
        [self.height uninstall];
    }

    [super updateConstraints];
}
  • 如果不需要顯示就設定高度約束為0
  • 如果需要顯示就把高度約束去掉

這個方法超級重要,有些view需要顯示的話,一定要把高度約束去掉,不然cell迴圈使用的話會出問題。

然後就是設定要顯示的text

-(void)setText:(NSString *)text {
    _text=text;
    self.textView.text = text;

    if ([self.text isEqualToString:@"123456789012345678901234567890"]) {
        self.isShowView = NO;
        self.button.hidden=YES;
        self.content.hidden=YES;
        self.intextView.hidden=YES;
    }else {
        self.isShowView = YES;
        self.button.hidden=NO;
        self.content.hidden=NO;
        self.intextView.hidden=NO;

    }
}

接下來在Controller檔案中
將cellForRowAtIndexPath方法改為下面樣子

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

    cell.text = self.tableData[indexPath.row];

    //返回cell之前重新重新整理約束,重新計算高度
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];

    return cell;
}

然後在-viewDidLoad方法中增加兩句話就行了

self.tableView.estimatedRowHeight = 200;
self.tableView.rowHeight = UITableViewAutomaticDimension;

接下來是支援iOS7的

只需要重寫程式碼方法heightForRowAtIndexPath

將這個方法內容改為下面這樣:

//如果要支援iOS7這個方法必須實現
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    self.cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"cell"];


    MyTableViewCell *cell = self.cell;
    cell.text = [self.tableData objectAtIndex:indexPath.row];

    //這句程式碼必須要有,也就是說必須要設定contentView的寬度約束。
    //設定以後,contentView裡面的內容才知道什麼時候該換行了
    CGFloat contentViewWidth = CGRectGetWidth(self.tableView.frame);
    [cell.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(@(contentViewWidth));
    }];

    //重新載入約束,每次計算之前一定要重新確認一下約束
    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];

    //自動算高度,+1的原因是因為contentView的高度要比cell的高度小1
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;

    return height;
}

好了大概就是這樣吧,具體demo點這裡

相關推薦

使用autolayout定義動態高度cell

關於使用autolayout建立動態cell,網上也有不少的文章,但是裡面的內容都是說的一個問題,簡稱換湯不換藥,都是說的一些UILabel或者UITextView等等一些控制元件顯示的文字內容不同來實現不同的高度。 但是我們平常使用的自定義cell很多都是顯

IONIC定義動態高度SubHeader的解決方案

IONIC subheader是我們常用的一個css 屬性,但是這個subheader的高度是固定的,當然也是可以改變的,但是如果改了subheader的告訴,還要更改content的top值,稍微有些麻煩,如果是動態告訴的subheader就麻煩了,還需要動態

iOS中最簡單實用的定義動態返回行高的cell動態計算cell高度

      iOS專案開發中,需要動態返回行高自定義cell的場景可以說是數不過來,可以不誇張的說,只要伺服器返回的同一個欄位的文字字數無限制,那麼我們客戶端在設定的時候就要動態返回行高。      場景:1.當需要tableview展示資料時,一般頭像,暱稱,等資訊都

WF4.0以上使用代碼完整定義動態生成執行工作流Xaml文件

load 控制 brush 類型 rpv 返回 cap 並且 sco 給大家分享一下,如何完全使用代碼自定義的創建生成工作流文件(用代碼創建Xaml文件),並且動態加載運行所生成的工作流。 工作流生成後 在Xaml文件裏的主要節點如下: 輸入輸出參數 <x

vue2入坑隨記(二) -- 定義動態組件

blank -1 reat files 但是 name define 構建 prototype 學習了Vue全家桶和一些UI基本夠用了,但是用元素的方式使用組件還是不夠靈活,比如我們需要通過js代碼直接調用組件,而不是每次在頁面上通過屬性去控制組件的表現。下面講一下如何定

實現類似微信表情包橫向滾動翻頁的功能,運用UICollectionView,定義UICollectionViewFlowLayout,cell左右排版 ,支持多組Cell實現。

hang sig idt 滾動翻頁 功能 details assign 實現類 targe 結合:https://blog.csdn.net/qiuhaozhou/article/details/54582741 下面是我所要的樣式的實現的代碼: .h文件如下: #i

【金蝶K3Cloud】 定義動態表單顯示外部網頁連結。

  前提: 由於想研究下,如何在金蝶K3Cloud中外掛自己的網頁或者BI 或者報表,所以反編譯了一次標準產品的經營分析平臺(BI)在金蝶K3Cloud連結的實現。 第一步: 新建動態表單   第二步: 拖一個面板控制元件,充滿整個動態表單。   第三步: 註

小白學ES 12 - 什麼是Elasticsearch的動態對映 + 如何定義動態對映

文章目錄 1 動態對映(dynamic mapping) 1.1 什麼是動態對映 1.2 體驗動態對映 1.3 搜尋結果不一致的原因分析 2 開啟dynamic mapping策略 2.1 約束策略

Masonry適配——(7)UITableView中定義UITableViewCell高度適應及計算

在UITableView列表的使用中,因為在自定義的UITableViewCell中頁面相對複雜,所以會出現每一個cell都有不同的高度。這時候就需要根據實際內容進行cell的更新約束,其實說到底也就是哪些UI子檢視應該顯示,或隱藏,哪些UILabel標籤高度是這個數值,

Spring AOP+反射實現定義動態配置校驗規則,讓校驗規則飛起來

場景小計 之前專案都是使用hibernate-validator來校驗引數,但是實際上會出現一些小問題,就是校驗規則都是通過註解的方式來完成,這樣如果專案上線了,這個引數校驗規則就沒辦法修改,如果出現校驗規則問題,就必須修改後重新緊急上線(之前因為手機

使用 dynamic_templates定義動態索引

如果你想在執行時的增加新的欄位,你可能會開啟動態索引。雖然有時動態對映的 規則 顯得不那麼智慧,幸運的是我們可以通過設定來自定義這些規則。 當 Elasticsearch 遇到一個新的字串欄位時,它會檢測這個欄位是否包含一個可識別的日期,比如 2014-01-01。如果它看

UItextView定義高度,禁止滾動

/* 返回指定內容的textView控制元件高度 value:指定的控制元件內容 fontSize:指定的控制元件內容字號 width:控制元件寬度 */ - (float) heightF

mybatis定義動態sql傳入物件

現在有一需求,要求頁面顯示懸賞列表,要求該懸賞未過期,沒有人接受以及附帶分頁查詢。 這裡我們很容易能得到滿足該需求的sql語句: select * from bounty where DeadTime > nowtime AND s

Raspberry Pi樹莓派上的定義動態開機畫面

指南:Raspberry Pi上的自定義動態開機畫面,Raspbian Jessie 網際網路上有許多指南在Linux上建立自定義啟動螢幕,但大多數Raspbian都基於SysV init,並且不能與Raspbian現在使用的systemd介面良好。因此,我已經寫了這個指南,直接將簡單的init風格的s

APEX 定義動態操作

自定義動態操作,可以通過一個按鈕或連結進行多個不同操作: 以下的例子是為了實現標誌當前的記錄是否已經列印的功能,點選表格中的列印欄位進行標記。 1.新建兩個項值分別存放當前記錄的ID和列印標誌is_print 2.建立動態操作,自定義型別 3.建立事件:其中兩

定義UiTableViewCell高度

@interface DemoCell : NSObject{    UILabel *_content; } -(CGFloat)contentHeight; -(void)setContent:(NSString *)content; @end; 從上面的DemoCell來看其帶有一個UILabel物

使用Autolayout xib實現動態高度的TableViewCell

前言 最近又要做新功能了,雖然沒有什麼難點,只是獲取後端XML資料顯示到TableView,但是不是可以更簡單快速的完成呢?原來Cell的動態高度一直都是通過sizeWithFont手動計算,潛意識覺得這應該不是最好的實現方式,但由於當時時間緊不允許嘗試新技術,所以問題也就遺留了下來,這次又遇到了,時間充裕

定義不等高cell的storyboard方法

對比自定義等高cell,需要幾個額外的步驟(iOS8開始才支援) 新增子控制元件和contentView之間的間距約束 設定tableViewCell的真實行高和估算行高 // 告

定義等高cell(frame和masonry方式)

程式碼自定義cell方法 程式碼自定義cell(使用frame) 1.建立一個繼承自UITableViewCell的子類,比如WQDealCell 在initWithStyle:reuseIdentifier:方法中 新增子控制元件 設定子控制元件的初

AutoLayout定義tableViewCell --- Masonry + UITableView+FDTemplateLayoutCell 純程式碼實現

AutoLayout自定義tableViewCell — Masonry + UITableView+FDTemplateLayoutCell 純程式碼實現 在被frame虐的體無完膚的樓主,在新專案開始的時候毅然決定使用Autolayout來實現專案的絕