Özel UITableViewCells yüksekliğini ayarlama


222

Görüntülenecek bazı etiketler, düğmeler ve görüntü görünümleri olan özel bir UITableViewCell kullanıyorum. Hücrede, metni bir NSStringnesne olan ve dize uzunluğu değişken olabilen bir etiket vardır . Bu nedenle, UITableView' heightForCellAtIndexyönteminde hücreye sabit bir yükseklik ayarlayamıyorum . Hücrenin boyu kullanılarak belirlenebilir etiketin yüksekliğine bağlıdır NSStringbireyin sizeWithFontyöntem. Kullanmayı denedim, ama bir yerlerde yanlış gidiyorum gibi görünüyor. Nasıl düzeltilebilir?

Hücreyi başlatmak için kullanılan kod.

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];
}

Bu, yüksekliği ve genişliği yanlış giden etikettir:

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

Yanıtlar:


499

Sizin UITableViewDelegateuygulamalıdırtableView:heightForRowAtIndexPath:

Objective-C

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

Hızlı 5

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

Muhtemelen kullanmak isteyeceğiniz NSString'ın sizeWithFont:constrainedToSize:lineBreakMode:sadece indexPath bazı saçma matematik performans yerine, satır yüksekliğini hesaplamak için bir yöntem :)


1
Şunu mu demek istediniz: [indexPath row] + 20?
fulvio

11
Fulvio: hayır, amaç sıraların bariz şekilde farklı yüksekliklerde olmasını sağlamaktı.
rpetrich

5
Belirli bir yüksekliğe ayarlamak için (örn. 44 piksel): 44;
mpemburn

Bu boyutun nasıl kullanılacağı hakkında daha fazla bilgi verebilir misinizWithFont: constrainedToSize: lineBreakMode:? Hücremde bir textView var ve yüksekliğini heightForRowAtIndexPath: almak istiyorum: satırın yüksekliğini ayarlamak için, ama nasıl elde edeceğimi bilmiyorum! Teşekkürler
rdurand

"[İndex row] * (some-value)" döndürürseniz, döndürdüğü ilk değer sıfır olduğu için ilk hücre görünmeyebilir. Bu nedenle, gerekli olan hücre yüksekliğini hesaplamak ve tüm hücreleri görünür hale getirmek için bu hesaplanan değeri buraya döndürmek daha iyidir
Vinayak GH

134

Tüm satırlarınız aynı yükseklikte rowHeightise, UITableView özelliğini uygulamak yerine özelliğini ayarlayın heightForRowAtIndexPath. Apple Dokümanlar:

RowHeight yerine tableView: heightForRowAtIndexPath: kullanmanın performansla ilgili sonuçları vardır. Bir tablo görünümü her görüntülendiğinde, satırlarının her biri için temsilci üzerinde tableView: heightForRowAtIndexPath: öğesini çağırır, bu da çok sayıda satıra (yaklaşık 1000 veya daha fazla) sahip tablo görünümlerinde önemli bir performans sorunuyla sonuçlanabilir.


5
Bu, tüm satırlar aynı yüksekliğe sahip olduğunda mükemmel şekilde çalışır. Orijinal poster, bu duruma sahip değildir, bu yüzden cevap kendi içinde yanlış değildir, ancak orijinal soruyu cevaplamaz. Ancak , rowHeight ayarının büyük olasılıkla heightForRowAtIndexPath geçersiz kılmasından daha iyi performans sağladığını belirtmek önemlidir, çünkü bu durumda kaydırma çubuğu boyutlarını hesaplamak gibi şeyler O (n) yerine O (1) olur.
Daniel Albuschat

2
Ayrıca (açık nedenlerden dolayı) tableView.rowHeight, ayarlandıysa, heightForRowAtIndexPathnedenini (benim gibi) anlamaya çalışmanız durumunda çağrılmayacağını unutmayın.
devios1

25

özel bir UITableViewCell denetleyicisine bunu ekleyin

-(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];
}

UITableView denetleyicisine bunu ekleyin

- (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

Çok fazla çözüm gördüm ama hepsi yanlış ya da eksikti. ViewDidLoad ve autolayout'ta 5 satırla tüm sorunları çözebilirsiniz. Bu objektif C için:

_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) ;

Hızlı 2.0 için:

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

Şimdi hücrenizi xib ile veya Storyboard'unuzdaki tablo görünümüne oluşturun. (0 numaralı os satırını unutmayın) ve alt etiket (kısıtlama) eski sürüme geçiyor "İçerik Hugging Önceliği - Dikey ila 250"

resim açıklamasını buraya girin resim açıklamasını buraya girin

Kodu bir sonraki url'ye yükleyebilirsiniz: https://github.com/jpose22/exampleTableCellCustomHeight


1
2 gün içinde chars ImageView ile aynı hücre ile daha fazla görüntü koyacağım ve diğer alt tablo görünümü bu yöntem her zaman çalışır. +1 için gerçekten teşekkürler.
Jose Pose S

Bu harika!! Başkalarına da yardımcı olacaktır. Teşekkürler :)
jagdish

Söz verdiğimiz gibi, burada yeni bir kod ve yeni bir resminiz var.
Jose Pose S

Çok teşekkürler ... devam et ...- :)
jagdish

UITableViewCell'i programlı olarak oluşturuyorsanız, örneğin Arayüz Oluşturucu'yu kullanmıyorsanız bu çözüm çalışmaz
MB_iOSDeveloper

6

Satır yüksekliği ve tahmini satır yüksekliği için otomatik boyut ayarlamak üzere, hücre / satır yüksekliği düzeni için otomatik boyutun etkili olmasını sağlamak üzere aşağıdaki adımları uygulayın.

  • Tablo görünümü verilerini atama ve uygulama Kaynak ve temsilci seçme
  • UITableViewAutomaticDimensionRowHeight ve TahminiRowHeight'a ata
  • Temsilci / dataSource yöntemlerini uygulama (yani buna heightForRowAtbir değer döndürme UITableViewAutomaticDimension)

-

Hedef 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;
}

Swift:

@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
}

UITableviewCell'deki etiket örneği için

  • Satır sayısını ayarlayın = 0 (& satır sonu modu = kesik kuyruk)
  • Denetleme / hücre kabına göre tüm kısıtlamaları (üst, alt, sağ sol) ayarlayın.
  • İsteğe bağlı : Etiket olmasa bile etiketle kaplı minimum dikey alan istiyorsanız, etiket için minimum yüksekliği ayarlayın.

resim açıklamasını buraya girin

Not : İçerik boyutuna göre ayarlanması gereken birden fazla dinamik uzunluğa sahip etiketiniz (UIElements) varsa: Daha yüksek önceliğe sahip genişletmek / sıkıştırmak istediğiniz etiketler için 'İçerik Sarılma ve Sıkıştırma Direnci Önceliği'ni ayarlayın.

Bu örnekte, düşük sarılma ve yüksek sıkıştırma direnci önceliğini ayarladım, bu da ikinci (sarı) etiketin içeriği için daha fazla öncelik / önem ayarlamasına yol açar.

resim açıklamasını buraya girin


5

Bu konudaki tüm yayınlar sayesinde, bir UITableViewCell'in rowHeight değerini ayarlamak için gerçekten yararlı bazı yollar vardır.

İşte iPhone ve iPad için geliştirirken gerçekten yardımcı olan bazı konseptlerden derleme. Ayrıca farklı bölümlere erişebilir ve bunları farklı görünüm boyutlarına göre ayarlayabilirsiniz.

- (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;
} 

XCode içinde analiz ederken, "int cellHeight;" bir mantık hatası oluşturdu, "Tanımsız veya çöp değeri arayana döndürüldü." CellHeight değerini 0 olarak ayarlayarak hatayı düzelttim. Bu hata, yukarıdaki if / else if ifadesine benzer bir switch deyiminin içinde nil için bir NSString ayarlamazsanız da görünür.
whyoz

3

Etiket metni arttıkça dinamik hücre yüksekliğine sahip olmak için, önce metni -heightForRowAtIndexPathtemsilci yönteminde kullanacak yüksekliği hesaplamanız ve diğer etiketlerin, görüntülerin ek yükseklikleri ile döndürmeniz gerekir (maksimum metin yüksekliği + diğer statik yükseklik) ekleyin) ve hücre oluşturmada aynı yüksekliği kullanın.

#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 Aşağı oylama yapmak için Tisho kardeşini test ettiniz. Dikkatlice test edin, kardeşim !!!!
Samir Jwarchan

1
Cevabınızı küçümsemedim. Biçimlendirmeyi yeni geliştirdim.
Tisho
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.