Содержимое ячейки UITableView не отображается должным образом
Я использую автоматический макет и хочу отображать UITableView
с пользовательской ячейкой с UITextView
с содержимым переменной.
Ячейки отображаются, как показано ниже. Для сообщения чата, когда ячейка сначала отображается, в одной строке отображаются только 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
. Все еще ячейка не выложена правильно. Я добавляю фотографии для ограничений каждого объекта пользовательского интерфейса в ячейке.
Имя пользователя:
Отметка времени:
Сообщение чата:
Изображение пузыря:
Макет ячейки:
-
Высота ячейки в cellForRowAtIndexPath:
всегда равна 100, хотя я возвращаю другое значение из метода heightForRowAtIndexPath:
. Высота ячейки в раскадровке составляет 100.
-
Сообщение чата в третьей ячейке обрезается снизу.
-
Временные метки и ярлыки сообщений чата некоторое время не выравниваются должным образом друг к другу, хотя оба имеют ограничение vertical spacing from username label
.
-
Имя пользователя в третьей ячейке исчезло.
Вы видите что-то не так в ограничениях? Вы можете спросить меня, трудно ли анализировать ограничения.
Ответы
Ответ 1
Объединив ответы на 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 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;
Ответ 2
Динамическую динамику ячейки можно определить так, чтобы текст отображался на одной строке. Я дал 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 height after calculating the area that text needs
}
Ответ 3
Вы устанавливаете кадр текста и вызываете 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
s не забудьте также установить preferredMaxLayoutWidth
на ширину меток, иначе текст может быть неверным:
- (void)layoutSubviews
{
[super layoutSubviews];
self.label.preferredMaxLayoutWidth = self.label.frame.size.width;
[super layoutSubviews];
}
Кроме того, метод вычисления высоты не должен делать то же самое, что и cellForRowAtIndexPath:
, если вы хотите использовать тот же код, просто вызовите этот другой метод для получения ячейки.