Mengatur tinggi UITableViewCells kustom


222

Saya menggunakan UITableViewCell khusus yang memiliki beberapa label, tombol, dan tampilan gambar untuk ditampilkan. Ada satu label di sel yang teksnya adalah NSStringobjek dan panjang string bisa variabel. Karena ini, saya tidak dapat menetapkan tinggi konstan ke sel dalam metode UITableView's heightForCellAtIndex. Tinggi sel tergantung pada ketinggian label yang dapat ditentukan dengan menggunakan NSString's sizeWithFontmetode. Saya mencoba menggunakannya, tetapi sepertinya saya salah di suatu tempat. Bagaimana bisa diperbaiki?

Berikut adalah kode yang digunakan untuk menginisialisasi sel.

if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier])
{
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    UIImage *image = [UIImage imageNamed:@"dot.png"];
    imageView = [[UIImageView alloc] initWithImage:image];
    imageView.frame = CGRectMake(45.0,10.0,10,10);

    headingTxt = [[UILabel alloc] initWithFrame:   CGRectMake(60.0,0.0,150.0,post_hdg_ht)];
    [headingTxt setContentMode: UIViewContentModeCenter];
    headingTxt.text = postData.user_f_name;
    headingTxt.font = [UIFont boldSystemFontOfSize:13];
    headingTxt.textAlignment = UITextAlignmentLeft;
    headingTxt.textColor = [UIColor blackColor];

    dateTxt = [[UILabel alloc] initWithFrame:CGRectMake(55.0,23.0,150.0,post_date_ht)];
    dateTxt.text = postData.created_dtm;
    dateTxt.font = [UIFont italicSystemFontOfSize:11];
    dateTxt.textAlignment = UITextAlignmentLeft;
    dateTxt.textColor = [UIColor grayColor];

    NSString * text1 = postData.post_body;
    NSLog(@"text length = %d",[text1 length]);
    CGRect bounds = [UIScreen mainScreen].bounds;
    CGFloat tableViewWidth;
    CGFloat width = 0;
    tableViewWidth = bounds.size.width/2;
    width = tableViewWidth - 40; //fudge factor
    //CGSize textSize = {width, 20000.0f}; //width and height of text area
    CGSize textSize = {245.0, 20000.0f}; //width and height of text area
    CGSize size1 = [text1 sizeWithFont:[UIFont systemFontOfSize:11.0f]
                        constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];

    CGFloat ht = MAX(size1.height, 28);
    textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];
    textView.text = postData.post_body;
    textView.font = [UIFont systemFontOfSize:11];
    textView.textAlignment = UITextAlignmentLeft;
    textView.textColor = [UIColor blackColor];
    textView.lineBreakMode = UILineBreakModeWordWrap;
    textView.numberOfLines = 3;
    textView.autoresizesSubviews = YES;

    [self.contentView addSubview:imageView];
    [self.contentView addSubview:textView];
    [self.contentView addSubview:webView];
    [self.contentView addSubview:dateTxt];
    [self.contentView addSubview:headingTxt];
    [self.contentView sizeToFit];

    [imageView release];
    [textView release];
    [webView release];
    [dateTxt release];
    [headingTxt release];
}

Ini adalah label yang tinggi dan lebarnya salah:

textView = [[UILabel alloc] initWithFrame:CGRectMake(55.0,42.0,245.0,ht)];

Jawaban:


499

Anda UITableViewDelegateharus menerapkantableView:heightForRowAtIndexPath:

Objektif-C

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [indexPath row] * 20;
}

Cepat 5

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return indexPath.row * 20
}

Anda mungkin akan ingin menggunakan NSString's sizeWithFont:constrainedToSize:lineBreakMode:metode untuk menghitung tinggi baris Anda bukan hanya melakukan beberapa matematika konyol di indexPath yang :)


1
Bukankah maksud Anda [baris indexPath] + 20?
fulvio

11
Fulvio: tidak, intinya adalah membuat baris memiliki ketinggian yang jelas berbeda.
rpetrich

5
Untuk mengatur ke ketinggian tertentu (misalnya, 44 piksel): mengembalikan 44;
mpemburn

Bisakah Anda memberikan beberapa detail lebih lanjut tentang cara menggunakan ukuran iniWithFont: constrainedToSize: lineBreakMode:? Saya memiliki textView di sel saya, dan saya ingin mendapatkan ketinggiannya di heightForRowAtIndexPath: untuk mengatur tinggi baris, tapi saya tidak tahu bagaimana cara mendapatkannya! Terima kasih
rdurand

Jika Anda mengembalikan "[baris indeks] * (beberapa nilai)" maka, sel pertama mungkin tidak terlihat karena nilai pertama yang dikembalikan adalah nol. Oleh karena itu lebih baik Anda menghitung tinggi sel yang dibutuhkan dan mengembalikan nilai yang dihitung di sini untuk membuat semua sel terlihat
Vinayak GH

134

Jika semua baris Anda sama tingginya, cukup tetapkan rowHeightproperti UITableView daripada menerapkan heightForRowAtIndexPath. Apple Documents:

Ada implikasi kinerja untuk menggunakan tableView: heightForRowAtIndexPath: bukannya rowHeight. Setiap kali tampilan tabel ditampilkan, ia memanggil tableView: heightForRowAtIndexPath: pada delegasi untuk setiap barisnya, yang dapat mengakibatkan masalah kinerja yang signifikan dengan tampilan tabel memiliki sejumlah besar baris (sekitar 1000 atau lebih).


5
Ini berfungsi dengan baik jika semua baris memiliki ketinggian yang sama. Poster asli, meskipun, tidak memiliki situasi itu, jadi jawabannya sendiri tidak salah, tetapi tidak menjawab pertanyaan aslinya. NAMUN Saya merasa penting untuk dicatat bahwa pengaturan rowHeight kemungkinan besar menghasilkan kinerja yang lebih baik daripada mengganti tinggi ForRowAtIndexPath karena hal-hal seperti menghitung dimensi scrollbar adalah O (1) daripada O (n) dalam kasus itu.
Daniel Albuschat

2
Perhatikan juga (untuk alasan yang jelas) bahwa jika tableView.rowHeightdisetel, heightForRowAtIndexPathtidak akan dipanggil, jika Anda mencoba mencari tahu mengapa (seperti saya).
devios1

25

dalam UITableViewCell kustom -controller tambahkan ini

-(void)layoutSubviews {  

    CGRect newCellSubViewsFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    CGRect newCellViewFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);

    self.contentView.frame = self.contentView.bounds = self.backgroundView.frame = self.accessoryView.frame = newCellSubViewsFrame;
    self.frame = newCellViewFrame;

    [super layoutSubviews];
}

Dalam UITableView -controller tambahkan ini

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [indexPath row] * 1.5; // your dynamic height...
}

CGRect newCellSubViewsFrame = self.bounds; CGRect newCellViewFrame = self.frame;
Pizzaiola Gorgonzola

17
#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 300.0f
#define CELL_CONTENT_MARGIN 10.0f

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath      *)indexPath;
{
   /// Here you can set also height according to your section and row
   if(indexPath.section==0 && indexPath.row==0)
   {
     text=@"pass here your dynamic data";

     CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

     CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE]      constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

     CGFloat height = MAX(size.height, 44.0f);

     return height + (CELL_CONTENT_MARGIN * 2);
   }
   else
   {
      return 44;
   }
}

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    UILabel *label = nil;

    cell = [tv dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil)
    {
       cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];
    }
    ********Here you can set also height according to your section and row*********
    if(indexPath.section==0 && indexPath.row==0)
    {
        label = [[UILabel alloc] initWithFrame:CGRectZero];
        [label setLineBreakMode:UILineBreakModeWordWrap];
        [label setMinimumFontSize:FONT_SIZE];
        [label setNumberOfLines:0];
        label.backgroundColor=[UIColor clearColor];
        [label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
        [label setTag:1];

        // NSString *text1 =[NSString stringWithFormat:@"%@",text];

        CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

        if (!label)
        label = (UILabel*)[cell viewWithTag:1];


        label.text=[NSString stringWithFormat:@"%@",text];
        [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH          - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
        [cell.contentView addSubview:label];
    }
return cell;
}

8
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    CGSize constraintSize = {245.0, 20000}
    CGSize neededSize = [ yourText sizeWithFont:[UIfont systemFontOfSize:14.0f] constrainedToSize:constraintSize  lineBreakMode:UILineBreakModeCharacterWrap]
if ( neededSize.height <= 18) 

   return 45
else return neededSize.height + 45 
//18 is the size of your text with the requested font (systemFontOfSize 14). if you change fonts you have a different number to use  
// 45 is what is required to have a nice cell as the neededSize.height is the "text"'s height only
//not the cell.

}

8

Saya melihat banyak solusi tetapi semuanya salah atau tidak lengkap. Anda dapat menyelesaikan semua masalah dengan 5 baris di viewDidLoad dan autolayout. Ini untuk objektif C:

_tableView.delegate = self;
_tableView.dataSource = self;
self.tableView.estimatedRowHeight = 80;//the estimatedRowHeight but if is more this autoincremented with autolayout
self.tableView.rowHeight = UITableViewAutomaticDimension;
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0) ;

Untuk swift 2.0:

 self.tableView.estimatedRowHeight = 80
 self.tableView.rowHeight = UITableViewAutomaticDimension      
 self.tableView.setNeedsLayout()
 self.tableView.layoutIfNeeded()
 self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)

Sekarang buat sel Anda dengan xib atau menjadi tableview di Storyboard Anda. Dengan ini Anda tidak perlu menerapkan apa-apa lagi atau menimpanya. (Jangan lupa nomor os baris 0) dan label bawah (membatasi) downgrade "Prioritas Konten Memeluk - Vertikal ke 250"

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Anda dapat memuat kode di url berikutnya: https://github.com/jposes22/exampleTableCellCustomHeight


1
Dalam 2 hari saya akan menempatkan lebih banyak gambar dengan sel yang sama dengan karakter ImageView, dan tampilan subtable lainnya metode ini selalu berfungsi. Terima kasih untuk +1 sungguh.
Jose Pose S

Itu hebat!! Ini akan membantu orang lain juga. Terima kasih :)
jagdish

Jadi, seperti yang dijanjikan, di sini Anda memiliki kode baru dan gambar baru.
Jose Pose S

Terima kasih banyak ... teruskan ...- :)
jagdish

Solusi ini tidak berfungsi jika Anda membuat UITableViewCell secara terprogram misalnya tidak menggunakan Interface Builder
MB_iOSDeveloper

6

Untuk mengatur dimensi otomatis untuk tinggi baris & perkiraan tinggi baris, pastikan langkah-langkah berikut untuk membuat, dimensi otomatis efektif untuk tata letak tinggi sel / baris.

  • Tetapkan dan laksanakan tableview sumber Data dan delegasikan
  • Menetapkan UITableViewAutomaticDimension ke rowHeight & estimasiRowHeight
  • Menerapkan metode delegasi / sumber data (yaitu heightForRowAtdan mengembalikan nilai UITableViewAutomaticDimensionke sana)

-

Sasaran C:

// in ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

  @property IBOutlet UITableView * table;

@end

// in ViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    self.table.dataSource = self;
    self.table.delegate = self;

    self.table.rowHeight = UITableViewAutomaticDimension;
    self.table.estimatedRowHeight = UITableViewAutomaticDimension;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return UITableViewAutomaticDimension;
}

Cepat:

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension
}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

Untuk contoh label di UITableviewCell

  • Tetapkan jumlah baris = 0 (& mode break baris = truncate tail)
  • Atur semua kendala (atas, bawah, kiri kanan) sehubungan dengan wadah superview / selnya.
  • Opsional : Tetapkan tinggi minimum untuk label, jika Anda ingin area vertikal minimum yang dicakup oleh label, bahkan jika tidak ada data.

masukkan deskripsi gambar di sini

Catatan : Jika Anda memiliki lebih dari satu label (UIElements) dengan panjang dinamis, yang harus disesuaikan dengan ukuran kontennya: Sesuaikan 'Prioritas Pelukan Konten dan Ketahanan Kompresi` untuk label yang ingin Anda perluas / kompres dengan prioritas lebih tinggi.

Di sini, dalam contoh ini saya menetapkan prioritas pelukan rendah dan resistensi kompresi tinggi, yang mengarah pada menetapkan lebih banyak prioritas / kepentingan untuk isi label kedua (kuning).

masukkan deskripsi gambar di sini


5

Berkat semua posting pada topik ini, ada beberapa cara yang sangat membantu untuk menyesuaikan rowHeight dari UITableViewCell.

Berikut adalah kompilasi dari beberapa konsep dari orang lain yang benar-benar membantu ketika membangun iPhone dan iPad. Anda juga dapat mengakses berbagai bagian dan menyesuaikannya sesuai dengan berbagai ukuran tampilan.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
    int cellHeight = 0;

    if ([indexPath section] == 0) 
    {
        cellHeight = 16;
        settingsTable.rowHeight = cellHeight;
    }
    else if ([indexPath section] == 1)
    {
        cellHeight = 20;
        settingsTable.rowHeight = cellHeight;
    }

    return cellHeight;
}
else
{
    int cellHeight = 0;

    if ([indexPath section] == 0) 
    {
        cellHeight = 24;
        settingsTable.rowHeight = cellHeight;
    }
    else if ([indexPath section] == 1)
    {
        cellHeight = 40;
        settingsTable.rowHeight = cellHeight;
    }

    return cellHeight;
}
return 0;
} 

Saat menganalisis dalam XCode, baris "int cellHeight;" membuat kesalahan logika, "Nilai tidak terdefinisi atau sampah dikembalikan ke pemanggil." Dengan mengatur cellHeight ke 0, ini memperbaiki kesalahan. Kesalahan ini juga akan muncul jika Anda tidak mengatur NSString ke nil di dalam pernyataan switch yang mirip dengan pernyataan if / else jika pernyataan di atas.
whyoz

3

Untuk memiliki tinggi sel dinamis ketika teks Label meningkat, pertama-tama Anda harus menghitung tinggi, bahwa teks akan digunakan dalam -heightForRowAtIndexPathmetode delegasi dan mengembalikannya dengan ketinggian tambahan dari lables lain, gambar (tinggi maksimum teks + tinggi statis lain) komponen) dan gunakan ketinggian yang sama dalam pembuatan sel.

#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 300.0f  
#define CELL_CONTENT_MARGIN 10.0f

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{

    if (indexPath.row == 2) {  // the cell you want to be dynamic

        NSString *text = dynamic text for your label;

        CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

        CGFloat height = MAX(size.height, 44.0f);

        return height + (CELL_CONTENT_MARGIN * 2);
    }
    else {
        return 44; // return normal cell height
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UILabel *label;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] ;
    }

    label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 280, 34)];

    [label setNumberOfLines:2];

    label.backgroundColor = [UIColor clearColor];

    [label setFont:[UIFont systemFontOfSize:FONT_SIZE]];

    label.adjustsFontSizeToFitWidth = NO;

    [[cell contentView] addSubview:label];


    NSString *text = dynamic text fro your label;

    [label setText:text];

    if (indexPath.row == 2) {// the cell which needs to be dynamic 

        [label setNumberOfLines:0];

        CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);

        CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];

        [label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];

    }
    return  cell;
}

@Tisho Sudahkah Anda mengujinya Tisho bro untuk melakukan pemungutan suara. Uji dengan hati-hati, itu berhasil bro !!!!
Samir Jwarchan

1
Saya belum menurunkan jawaban Anda. Saya baru saja memperbaiki format.
Tisho
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.