UITableView单元格内容不能正确显示

我使用自动布局,并希望显示具有可变内容的UITextView自定义单元格的UITableView

单元格显示如下所示。 对于聊天消息,当单元格第一次显示时, 只有2-3个字符显示在一行中 ,下一个字符被强制转到下一行。 但是,当我滚动tableView,使这些单元格不可见,并回滚,使他们可见(我这样做,以便当他们再次可见cellForRowAtIndexPath:方法被再次调用来呈现单元格),他们呈现正确的单元格第二个图像。

在这里输入图像说明在这里输入图像说明

代码:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [chatData count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { RS_User *user = [[RS_User alloc]init]; chatCell *cell = (chatCell *)[tableView dequeueReusableCellWithIdentifier:CHAT_CELL_IDENTIFIER]; NSUInteger row = indexPath.row; cell.chatCellBackground.image = nil; NSString *chatText = [[chatData objectAtIndex:row] objectForKey:TEXT]; // get text string(message) from array cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping; UIFont *font = [UIFont systemFontOfSize:FONT_SIZE]; cell.textString.font = [UIFont fontWithName:FONT_NAME size:FONT_SIZE]; // set text font cell.textString.text = chatText; // set text CGSize size = [cell.textString.text sizeWithFont:cell.textString.font constrainedToSize:CGSizeMake(SET_WIDTH, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping]; cell.textString.frame = ...; [cell.textString sizeToFit]; NSDate *theDate = [[chatData objectAtIndex:row] objectForKey:DATE]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:DATE_FORMAT]; NSString *timeString = [formatter stringFromDate:theDate]; cell.timeLabel.text = timeString; // set timeLabel to display date and time cell.timeLabel.font = [UIFont fontWithName:FONT_NAME size:SMALL_FONT_SIZE]; cell.userLabel.text = @"Name";//[[chatData objectAtIndex:row] objectForKey:NAME]; // set userLabel to display userName CGSize size1 = [cell.userLabel.text sizeWithFont:font constrainedToSize:CGSizeMake(SET_WIDTH, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping]; // check cell contains sender name or receiver name if (thisCellIsForSender) { // Set bubble for sender cell.chatCellBackground.image = [[UIImage imageNamed:@"bubbleMine.png"] stretchableImageWithLeftCapWidth:STRETCHED_WIDTH topCapHeight:STRETCHED_HEIGHT]; cell.chatCellBackground.frame = ...; } else { // set bubble for receiver cell.chatCellBackground.image = [[UIImage imageNamed:@"bubbleSomeone.png"] stretchableImageWithLeftCapWidth:STRETCHED_WIDTH topCapHeight:STRETCHED_HEIGHT]; cell.chatCellBackground.frame = ...; } [cell setNeedsLayout]; [cell layoutIfNeeded]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { RS_User *user = [[RS_User alloc]init]; chatCell *cell = (chatCell *)[tableView dequeueReusableCellWithIdentifier:CHAT_CELL_IDENTIFIER]; NSUInteger row = indexPath.row; cell.chatCellBackground.image = nil; NSString *chatText = [[chatData objectAtIndex:row] objectForKey:TEXT]; // get text string(message) from array cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping; UIFont *font = [UIFont systemFontOfSize:FONT_SIZE]; cell.textString.font = [UIFont fontWithName:FONT_NAME size:FONT_SIZE]; // set text font cell.textString.text = chatText; // set text CGSize size = [cell.textString.text sizeWithFont:cell.textString.font constrainedToSize:CGSizeMake(SET_WIDTH, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping]; cell.textString.frame = ...; [cell.textString sizeToFit]; NSDate *theDate = [[chatData objectAtIndex:row] objectForKey:DATE]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:DATE_FORMAT]; NSString *timeString = [formatter stringFromDate:theDate]; cell.timeLabel.text = timeString; // set timeLabel to display date and time cell.timeLabel.font = [UIFont fontWithName:FONT_NAME size:SMALL_FONT_SIZE]; cell.userLabel.text = [[chatData objectAtIndex:row] objectForKey:NAME]; // set userLabel to display userName [cell setNeedsUpdateConstraints]; [cell updateConstraintsIfNeeded]; CGSize size1 = [cell.userLabel.text sizeWithFont:font constrainedToSize:CGSizeMake(SET_WIDTH, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping]; // check cell contains sender name or receiver name if (thisCellIsForSender) { // Set bubble for sender cell.chatCellBackground.image = [[UIImage imageNamed:@"bubbleMine.png"] stretchableImageWithLeftCapWidth:STRETCHED_WIDTH topCapHeight:STRETCHED_HEIGHT]; cell.chatCellBackground.frame = ...; } else { // set bubble for receiver cell.chatCellBackground.image = [[UIImage imageNamed:@"bubbleSomeone.png"] stretchableImageWithLeftCapWidth:STRETCHED_WIDTH topCapHeight:STRETCHED_HEIGHT]; cell.chatCellBackground.frame = ...; } cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds)); [cell setNeedsLayout]; [cell layoutIfNeeded]; return cell.bounds.size.height; } 

更新:我可以从coverback的答案中解决一些问题。 静态单元格没有正确布置。 我正在为单元格中的每个UI对象的约束添加照片。

用户名 :

在这里输入图像说明在这里输入图像说明

时间戳:

在这里输入图像说明在这里输入图像说明

聊天消息:

在这里输入图像说明在这里输入图像说明

泡泡图像:

在这里输入图像说明在这里输入图像说明

单元格布局:

  • cellForRowAtIndexPath:单元格高度始终为100,即使我从heightForRowAtIndexPath:方法返回不同的值。 故事板中的单元格高度是100。

  • 第三个单元格中的聊天消息从底部剪切。

  • 时间戳和聊天消息标签有一段时间没有正确alignment,即使两者都有vertical spacing from username label限制。

  • 第三个单元格中的用户名标签消失。

在这里输入图像说明

你有没有看到任何错误的约束? 你可以问我,如果分析约束是困难的。

结合thandasoru和coverback的答案解决了我的问题。 以下是我使用的代码。

我在自定义的UITableViewCell的类中添加了下面的方法。

 - (void)layoutSubviews { [super layoutSubviews]; CGFloat maxTextWidth = [UIScreen mainScreen].bounds.size.width * 0.40; self.userLabel.preferredMaxLayoutWidth = maxTextWidth; self.chatMessage.preferredMaxLayoutWidth = maxTextWidth; self.timeLabel.preferredMaxLayoutWidth = self.timeLabel.frame.size.width; [super layoutSubviews]; } 

UITableView数据源方法:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { CustomCell * cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"customCellId"]; // Set all label's text and image to ImageView ... // Update layout [cell setNeedsLayout]; [cell layoutIfNeeded]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { customCell * cell = (customCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath]; NSString * userName = cell.userLabel.text; NSString * chatText = cell.chatMessage.text; // Get bounding rect of userName label CGRect userNameFrame = [userName boundingRectWithSize:CGSizeMake(maxLabelWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:cell.userLabel.font} context:nil]; // Get bounding rect of chatMessage label CGRect chatTextFrame = [chatText boundingRectWithSize:CGSizeMake(maxLabelWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:cell.chatMessage.font} context:nil]; // Calculate cell height from its contents height = userNameFrame.size.height + chatTextFrame.size.height + PADDING_ABOVE_TOP_LABEL + DISTANCE_BETWEEN_TWO_LABELS + PADDING_BELOW_BOTTOM_LABEL; return height; 

您可以dynamic确定单元格高度,以便文本显示在一行上。 我已经给CGSize(320,568)作为边界。 但是你可以根据你的需要改变尺寸

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *chatText = [[chatData objectAtIndex:row] objectForKey:TEXT]; CGRect frame = [chatText boundingRectWithSize:CGSizeMake(320,568) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:18.0f]} context:nil]; return frame.height; //returns cell's height after calculating the area that text needs } 

你正在设置文本的框架,并调用sizeToFit

  CGSize size = [cell.textString.text sizeWithFont:cell.textString.font constrainedToSize:CGSizeMake(SET_WIDTH, MAXFLOAT) lineBreakMode:NSLineBreakByCharWrapping]; cell.textString.frame = ...; [cell.textString sizeToFit]; 

这不会与自动布局。 您需要完全删除设置框架和sizeToFit ,直接设置所有其他框架。 如果事情不行之后,这将意味着一些限制是不正确的。 但混合方法总是打破布局。

对于UILabel ,请确保将preferredMaxLayoutWidth设置为标签的宽度,否则文本可能无法正确包装:

 - (void)layoutSubviews { [super layoutSubviews]; self.label.preferredMaxLayoutWidth = self.label.frame.size.width; [super layoutSubviews]; } 

另外,你的高度计算方法不应该和cellForRowAtIndexPath:如果你想使用相同的代码,只需调用另一个方法来获取单元格。