การตั้งค่าความสูง UITableViewCells ที่กำหนดเอง


222

ฉันใช้ UITableViewCell ที่กำหนดเองซึ่งมีป้ายกำกับปุ่มและมุมมองรูปภาพที่จะแสดง มีหนึ่งป้ายในเซลล์ที่มีข้อความเป็นNSStringวัตถุและความยาวของสตริงอาจเป็นตัวแปรได้ เนื่องจากนี้ฉันไม่สามารถตั้งค่าความสูงอย่างต่อเนื่องไปยังเซลล์ในส่วนUITableViewของheightForCellAtIndexวิธีการ ความสูงของเซลล์ที่ขึ้นอยู่กับความสูงของป้ายซึ่งสามารถตรวจสอบการใช้NSString's sizeWithFontวิธี ฉันลองใช้มัน แต่ดูเหมือนว่าฉันผิดไปที่ไหนซักแห่ง จะแก้ไขอย่างไร?

นี่คือรหัสที่ใช้ในการเริ่มต้นเซลล์

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:

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

คุณอาจจะต้องการใช้NSString's sizeWithFont:constrainedToSize:lineBreakMode:วิธีการคำนวณความสูงของแถวของคุณมากกว่าแค่การดำเนินการบางส่วนคณิตศาสตร์โง่ใน indexPath :) ความ


1
คุณไม่ได้หมายถึง [indexPath แถว] + 20 ใช่ไหม
fulvio

11
Fulvio: ไม่ประเด็นคือการทำให้แถวมีความสูงต่างกันอย่างเห็นได้ชัด
rpetrich

5
หากต้องการตั้งค่าความสูงเฉพาะ (เช่น 44 พิกเซล): ส่งคืน 44;
mpemburn

คุณสามารถให้รายละเอียดเพิ่มเติมเล็กน้อยเกี่ยวกับวิธีใช้ sizeWithFont นี้: constrainedToSize: lineBreakMode: ฉันมี textView ในเซลล์ของฉันและฉันต้องการได้ความสูงในระดับสูง ForRowAtIndexPath: เพื่อกำหนดความสูงของแถว แต่ฉันไม่รู้วิธีรับมัน! ขอบคุณ
rdurand

หากคุณส่งคืน "[ดัชนีแถว] * (บางค่า)" เซลล์แรกอาจไม่สามารถมองเห็นได้เนื่องจากค่าแรกที่ส่งคืนจะเป็นศูนย์ ดังนั้นจึงเป็นการดีกว่าที่คุณจะคำนวณความสูงของเซลล์ที่ต้องการและคืนค่าที่คำนวณได้ที่นี่เพื่อให้เซลล์ทั้งหมดมองเห็นได้
Vinayak GH

134

หากทุกแถวของคุณมีความสูงเดียวกันเพียงแค่ตั้งค่าrowHeightคุณสมบัติของ UITableView heightForRowAtIndexPathมากกว่าการดำเนินการ เอกสารของ Apple:

มีความเกี่ยวข้องกับประสิทธิภาพในการใช้ tableView: heightForRowAtIndexPath: แทนที่จะเป็น rowHeight ทุกครั้งที่มีการแสดงมุมมองตารางจะเรียกใช้ tableView: heightForRowAtIndexPath: บนผู้รับมอบสิทธิ์สำหรับแถวแต่ละแถวซึ่งอาจส่งผลให้เกิดปัญหาประสิทธิภาพที่สำคัญกับมุมมองตารางที่มีแถวจำนวนมาก (ประมาณ 1,000 หรือมากกว่า)


5
มันทำงานได้อย่างสมบูรณ์แบบเมื่อแถวทั้งหมดมีความสูงเท่ากัน แม้ว่าผู้โพสต์ดั้งเดิมจะไม่มีสถานการณ์เช่นนั้นดังนั้นคำตอบในตัวมันเองนั้นไม่ถูกต้อง แต่ไม่ได้ตอบคำถามดั้งเดิม อย่างไรก็ตามฉันคิดว่ามันสำคัญที่จะต้องทราบว่าการตั้งค่า rowHeight น่าจะให้ประสิทธิภาพที่ดี กว่าการเอาชนะ heightForRowAtIndexPath เพราะสิ่งต่าง ๆ เช่นการคำนวณขนาด scrollbar คือ O (1) แทนที่จะเป็น O (n) ในกรณีนั้น
Daniel Albuschat

2
ให้สังเกตด้วย (ด้วยเหตุผลที่ชัดเจน) ว่าถ้าtableView.rowHeightตั้งไว้heightForRowAtIndexPathจะไม่ถูกเรียกในกรณีที่คุณพยายามหาสาเหตุ (เหมือนฉัน)
devios1

25

ใน UITableViewCell แบบกำหนดเอง - ตัวควบคุมเพิ่มสิ่งนี้

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

ฉันเห็นวิธีแก้ปัญหามากมาย แต่ทั้งหมดนั้นผิดหรือไม่สมบูรณ์ คุณสามารถแก้ปัญหาทั้งหมดด้วย 5 บรรทัดใน viewDidLoad และการชำระอัตโนมัติ สิ่งนี้สำหรับ objetive 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) ;

สำหรับ 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)

ตอนนี้สร้างเซลล์ของคุณด้วย xib หรือลงใน tableview ใน Storyboard ของคุณด้วยสิ่งนี้คุณไม่จำเป็นต้องใช้อะไรมาก (อย่าลืมหมายเลข os บรรทัด 0) และเลเบลด้านล่าง (ข้อ จำกัด ) ปรับลดรุ่น "ลำดับความสำคัญของเนื้อหา Hugging - แนวตั้งเป็น 250"

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถโหลดรหัสใน URL ถัดไป: https://github.com/jposes22/exampleTableCellCustomHeight


1
ใน 2 วันฉันจะใส่ภาพเพิ่มเติมด้วยเซลล์เดียวกันกับ chars ImageView และมุมมองย่อยอื่น ๆ วิธีนี้ใช้งานได้เสมอ ขอบคุณสำหรับ +1 จริงๆ
Jose Pose S

เยี่ยมมาก !! มันจะช่วยผู้อื่นเช่นกัน ขอบคุณ :)
jagdish

ดังนั้นตามสัญญาที่นี่คุณมีรหัสใหม่และภาพใหม่
Jose Pose S

ขอบคุณมาก ... ติดตาม ...- :)
jagdish

โซลูชันนี้ใช้ไม่ได้หากคุณกำลังสร้าง UITableViewCell แบบเป็นระบบเช่นไม่ได้ใช้ตัวสร้างส่วนต่อ
ประสาน

6

ในการตั้งค่ามิติอัตโนมัติสำหรับความสูงของแถว & ความสูงของแถวโดยประมาณให้ทำตามขั้นตอนที่จะทำให้มิติอัตโนมัติมีประสิทธิภาพสำหรับโครงร่างความสูงของเซลล์ / แถว

  • กำหนดและใช้ tableview dataSource และผู้รับมอบสิทธิ์
  • กำหนดให้UITableViewAutomaticDimensionกับแถวความสูง & ประมาณแถวสูง
  • ใช้วิธีการมอบหมาย / 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

นี่คือการรวบรวมแนวคิดบางอย่างจากคนอื่น ๆ ที่ช่วยเมื่อสร้างสำหรับ 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 จะเป็นการแก้ไขข้อผิดพลาด ข้อผิดพลาดนี้จะปรากฏขึ้นหากคุณไม่ได้ตั้งค่า NSString เป็นศูนย์ภายในคำสั่งสวิตช์คล้ายกับคำสั่ง if / else ถ้าข้างต้น
Whyoz

3

ในการมีความสูงของเซลล์แบบไดนามิกเมื่อข้อความของ Label เพิ่มขึ้นอันดับแรกคุณต้องคำนวณความสูงก่อนว่าข้อความจะใช้ใน-heightForRowAtIndexPathวิธีมอบหมายและส่งกลับด้วยความสูงที่เพิ่มขึ้นของฉลากอื่น ๆ รูปภาพ (ความสูงสูงสุดของข้อความ + ความสูงอื่น ๆ componenets) และใช้ความสูงเท่ากันในการสร้างเซลล์

#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
ฉันไม่ได้ลงคะแนนคำตอบของคุณ ฉันเพิ่งปรับปรุงการจัดรูปแบบ
Tisho
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.