사용자 정의 UITableViewCells 높이 설정


222

표시 할 레이블, 버튼 및 이미지보기가있는 사용자 정의 UITableViewCell을 사용하고 있습니다. 셀에 텍스트가 NSString객체이고 문자열 길이가 변할 수있는 레이블이 하나 있습니다. 이로 인해 UITableViewheightForCellAtIndex메소드 에서 셀에 일정한 높이를 설정할 수 없습니다 . 셀의 높이는 NSStringsizeWithFont방법을 사용하여 결정할 수있는 레이블의 높이에 따라 다릅니다 . 나는 그것을 사용하려고했지만 어딘가에 잘못 가고있는 것처럼 보입니다. 어떻게 고칠 수 있습니까?

다음은 셀을 초기화하는 데 사용되는 코드입니다.

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

높이와 너비가 잘못 된 레이블입니다.

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

답변:


499

귀하는 UITableViewDelegate구현해야합니다tableView:heightForRowAtIndexPath:

목표 -C

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

스위프트 5

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

indexPath에서 바보 같은 수학을 수행하는 대신 행 높이를 계산하기 위해 NSStringsizeWithFont:constrainedToSize:lineBreakMode:방법 을 사용하고 싶을 것입니다. :)


1
[indexPath row] + 20을 의미합니까?
fulvio

11
풀비 오 : 아니요, 요점은 행이 분명히 다른 높이를 갖도록하는 것이 었습니다.
rpetrich

5
특정 높이 (예 : 44 픽셀)로 설정하려면 반환 44;
mpemburn

이 sizeWithFont : constrainedToSize : lineBreakMode : 사용 방법에 대한 몇 가지 세부 사항을 제공 할 수 있습니까? 셀에 textView가 있고 행의 높이를 설정하기 위해 heightForRowAtIndexPath :에서 높이를 얻고 싶습니다. 그러나 어떻게 얻는 지 모르겠습니다! 감사합니다
rdurand

"[index row] * (some-value)"를 반환하면 첫 번째 셀이 반환하는 첫 번째 값이 0이므로 첫 번째 셀이 보이지 않을 수 있습니다. 따라서 모든 셀을 보이게하려면 필요한 셀 높이를 계산하고 계산 된 값을 여기로 반환하는 것이 좋습니다.
Vinayak GH

134

모든 행의 높이가 동일한 rowHeight경우을 구현하지 않고 UITableView 의 속성을 설정 하십시오 heightForRowAtIndexPath. Apple Docs :

rowHeight 대신 tableView : heightForRowAtIndexPath :를 사용하면 성능에 영향을 미칩니다. 테이블 뷰가 표시 될 때마다 각 행의 대리자에서 tableView : heightForRowAtIndexPath :를 호출하여 행 수가 많은 테이블 뷰 (약 1000 이상)에서 성능 문제가 발생할 수 있습니다.


5
모든 행의 높이가 같을 때 완벽하게 작동합니다. 그러나 원래 포스터에는 그러한 상황이 없으므로 그 자체로 답은 정확하지 않지만 원래 질문에 대한 답은 아닙니다. 그러나 rowHeight를 설정 하면 스크롤 막대 크기 계산과 같은 항목이 O (n) 대신 O (1)이기 때문에 heightForRowAtIndexPath를 재정의하는 것 보다 성능더 우수 하다는 점에 유의해야합니다 .
Daniel Albuschat

2
이유 tableView.rowHeightheightForRowAtIndexPath무엇인지 알아 내려고 시도 하는 경우 (명백한 이유로) 호출되지 않습니다.
devios1

25

사용자 정의 UITableViewCell -controller에서 이것을 추가하십시오.

-(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 -controller에서 이것을 추가하십시오.

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

나는 많은 해결책을 보았지만 모두 잘못되었거나 완성되지 않았습니다. viewDidLoad 및 autolayout에서 5 줄의 모든 문제를 해결할 수 있습니다. 절제적인 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) ;

신속한 2.0의 경우 :

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

이제 스토리 보드에서 xib 또는 테이블 뷰로 셀을 만들면 더 이상 구현하거나 재정의 할 필요가 없습니다. (숫자 os 행 0을 잊어 버리지 않음) 및 맨 아래 레이블 (제한)은 "콘텐츠 포옹 우선 순위-수직을 250으로"다운 그레이드합니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

다음 URL에서 코드를 다운로드 할 수 있습니다 : https://github.com/jposes22/exampleTableCellCustomHeight


1
2 일 후에는 ImageView 문자가있는 동일한 셀에 더 많은 이미지를 넣고 다른 하위 테이블보기는이 방법이 항상 작동합니다. +1 감사합니다.
Jose Pose S

대단해 !! 다른 사람들에게도 도움이 될 것입니다. 감사합니다 :)
jagdish

약속했듯이 여기에 새로운 코드와 이미지가 있습니다.
Jose Pose S

고마워요 ... 계속 ...- :)
jagdish

당신이 인터페이스 빌더를 사용하지 않는 예를 들어 프로그래밍 방식있는 UITableViewCell을 만드는 경우이 솔루션은 작동하지 않습니다
MB_iOSDeveloper

6

행 높이 및 예상 행 높이에 대한 자동 치수를 설정하려면 다음 단계를 수행하여 셀 / 행 높이 레이아웃에 자동 치수를 적용하십시오.

  • 테이블 뷰 데이터 할당 및 구현
  • 양수인 UITableViewAutomaticDimensionrowHeight 및 추정 된 RowHeight에
  • 델리게이트 / dataSource 메소드 구현 (즉 heightForRowAt, 값 UITableViewAutomaticDimension을 반환 )

-

목표 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;
}

빠른:

@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의 레이블 인스턴스

  • 줄 수 설정 = 0 (& 줄 바꿈 모드 = 꼬리 자르기)
  • 수퍼 뷰 / 셀 컨테이너와 관련하여 모든 제한 조건 (상단, 하단, 오른쪽 왼쪽)을 설정하십시오.
  • 선택 사항 : 데이터가 없어도 레이블로 덮는 최소 세로 영역을 원하면 레이블의 최소 높이를 설정하십시오.

여기에 이미지 설명을 입력하십시오

참고 : 동적 길이의 레이블 (UIElements)이 둘 이상인 경우 컨텐츠 크기에 따라 조정해야합니다. 우선 순위가 더 높은 확장 / 압축하려는 레이블에 대해 '콘텐츠 포옹 및 압축 저항 우선 순위 조정'.

여기이 예에서는 낮은 포옹과 높은 압축 저항 우선 순위를 설정하여 두 번째 (노란색) 레이블의 내용에 대해 더 많은 우선 순위 / 중요도를 설정합니다.

여기에 이미지 설명을 입력하십시오


5

이 주제에 대한 모든 게시물 덕분에 UITableViewCell의 rowHeight를 조정하는 데 실제로 유용한 방법이 있습니다.

다음은 iPhone 및 iPad 용으로 제작할 때 실제로 도움이되는 다른 모든 사람의 일부 개념을 모은 것입니다. 다른 섹션에 액세스하여 다양한 뷰 크기에 따라 조정할 수도 있습니다.

- (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에서 분석 할 때 "int cellHeight;" "정의되지 않은 또는 가비지 값이 호출자에게 반환되었습니다."라는 논리 오류가 발생했습니다. cellHeight를 0으로 설정하면 오류가 수정되었습니다. 위의 if / else if 문과 비슷한 switch 문에서 NSString을 nil로 설정하지 않은 경우에도이 오류가 나타납니다.
whyoz

3

Label의 텍스트가 증가함에 따라 동적 셀 높이를 가지려면 먼저 텍스트를 -heightForRowAtIndexPath대리자 메서드에 사용할 높이를 계산 하고 다른 lables의 높이, 이미지 (최대 텍스트 높이 + 다른 정적 높이)로 반환해야합니다 셀 생성에 동일한 높이를 사용합니다.

#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 다운 쇼를하기 위해 Tisho bro를 테스트 했습니까? 신중하게 테스트하십시오.
사미르 Jwarchan

1
나는 당신의 대답을 downvoted하지 않았습니다. 방금 서식을 개선했습니다.
Tisho
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.