динамический расчет ширины UILabel в UITableViewCell - PullRequest
22 голосов
/ 22 декабря 2009

Я создаю собственное представление настроек в приложении на основе UITableViewCellStyle1 (или около того).

Я пытаюсь динамически рассчитать ширину левой метки (заголовка) ячейки, чтобы определить, насколько широким может быть мое текстовое поле справа.

Когда я запускаю приложение в симуляторе и загрузка загружается, ширина меток заголовка равна нулю, пока я не прокручиваю вид вниз, и ячейка не видна, а затем, когда я прокручиваю назад вверх, размер корректируется, как и ожидалось. Я считаю, что это может быть связано с повторным использованием клеток.

Мне нужно, чтобы метки заголовка в ячейках имели правильную ширину при загрузке вида, а не после того, как они исчезли один раз.

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
  {
      static NSString* reuseIdentifier = @"SettingsCell";

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

if ( !cell )
{   
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier] autorelease];
    [cell setBackgroundColor:[UIColor baeDarkGrayColor]];


    UILabel* cellLabel = [cell textLabel];
    [cellLabel setTextColor:[UIColor whiteColor]];
    [cellLabel setBackgroundColor:[UIColor clearColor]];

    [cell setUserInteractionEnabled:YES];
    [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
}

// Populate cell with corresponding data.
NSDictionary* tableSection = [_tableData objectAtIndex:indexPath.section];

// Set the label
UILabel* textLabel = [cell textLabel];
NSString* labelString = [[tableSection objectForKey:@"itemTitles"] objectAtIndex:indexPath.row];
[textLabel setText:labelString];

   //   CGSize constrainedSize;
  //    constrainedSize.width = MAXFLOAT;
 // constrainedSize.height = MAXFLOAT;

CGSize textLabelSize = [textLabel.text sizeWithFont:textLabel.font /*constrainedToSize:constrainedSize*/];

NSLog(@"text label width: %f", textLabelSize.width);    


// Set the accessory view
BAESettingsTableCellAccessoryType accessoryType = [[[tableSection objectForKey:@"itemAccessories"] objectAtIndex:indexPath.row] integerValue];
switch ( accessoryType )
{
    case BAESettingsTableCellAccessoryDisclosureIndicator:
    {
        UIImageView* disclosureView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"AccessoryDisclosure.png"]];
        [cell setAccessoryView:disclosureView];
        [disclosureView release];
        break;
    }
    case BAESettingsTableCellAccessoryOnOffSwitch:
    {
        UISwitch* onOffSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
        [onOffSwitch setOn:YES];
        [cell setAccessoryView:onOffSwitch];
        [onOffSwitch release];
        break;
    }
    case BAESettingsTableCellAccessoryNone:
        // default:
        // break;
    {

        CGRect cellFrame = [cell frame];

        float detailTextFieldWidth = cellFrame.size.width - ( textLabelSize.width + 50 );
        float detailTextFieldHeight = cellFrame.size.height - 1;

        NSLog(@"detail text field calculated frame width, height, %f, %f", detailTextFieldWidth, detailTextFieldHeight);


        CGRect frame = CGRectMake(cellFrame.origin.x, cellFrame.origin.y, detailTextFieldWidth, detailTextFieldHeight);


        UITextField* textField = [[UITextField alloc] initWithFrame:frame];
        NSString* detailLabelString = [[tableSection objectForKey:@"itemDetailStrings"] objectAtIndex:indexPath.row];
        textField.text = detailLabelString;
        textField.textColor = cell.detailTextLabel.textColor;
        textField.textAlignment = UITextAlignmentRight;
        textField.borderStyle = UITextBorderStyleRoundedRect;
        [cell setAccessoryView:textField];
        [textField release];
        break;
    }

}

return cell;
   }

Ответы [ 4 ]

16 голосов
/ 02 января 2010

Явная установка шрифта решает вашу проблему.

CGSize textLabelSize = [textLabel.text sizeWithFont:[UIFont systemFontOfSize:17]];

Горы Детальс:
Когда таблица впервые загружается, этот фрагмент возвращает нулевую ширину, поскольку размер шрифта равен 0.

[textLabel.text sizeWithFont:textLabel.font]

Я понял это, отобразив размер шрифта ячейки.

NSLog(@"font size: %f", cell.textLabel.font.pointSize);

Размер точки был нулевым, пока ячейка не исчезла с экрана и не вернулась, как вы описали.

5 голосов
/ 10 января 2011

Я полностью согласен, что это достаточно раздражает, что это должно быть ошибкой. Почему хорошие люди в Apple когда-либо просят высоту ячейки, не гарантируя, что ячейка полностью настроена. Глупо! Однако вместо использования устаревшей функции попробуйте:

[cell layoutIfNeeded];

Вызов этого метода имеет тот же эффект, что и настраиваемая ячейка, включая границы, шрифт ячейки и т. Д. Поэтому любые вычисления после этого имеют доступ к полностью настроенной ячейке. Вот весь код:

-(CGFloat) tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath {

  // Find the cell for this index path
  UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
  CGFloat cellHeight = cell.frame.size.height;

  // Calculate text size after forcing a layout
  [cell layoutIfNeeded];
  CGSize textSize = [cell.textLabel.text sizeWithFont:cell.textLabel.font constrainedToSize:CGSizeMake(cell.contentView.bounds.size.width, 99999) lineBreakMode:cell.textLabel.lineBreakMode];

  // Only change the cell height if the text forces a growth
  if (textSize.height > cellHeight) {
    cellHeight = textSize.height;
  }

  return cellHeight;
}
3 голосов
/ 23 мая 2011

Используйте [myLbl sizeToFit]; для автоматического изменения размера метки.

Вот пример кода.

UILabel *lbl1, *lbl2;
    if (cell == nil) {

   UILabel *lbl1 = [[UILabel alloc] init];
            [lbl1 setFont:[UIFont boldSystemFontOfSize:20]];
            [cell.contentView addSubview:lbl1];
            lbl1.frame = CGRectMake(3, 10, 0, 0);
            lbl1.tag = 10;
            [lbl1 release];

        UILabel *lbl2 = [[UILabel alloc] init];
        [lbl2 setFont:[UIFont systemFontOfSize:20]];
        [cell.contentView addSubview:lbl2];                 
        lbl2.tag = 20;
        [lbl2 release];
}
else {
       lbl1 = (UILabel*)[cell.contentView viewWithTag:10];
       lbl2 = (UILabel*)[cell.contentView viewWithTag:20];
}

  lbl1.text = @"Hello ";
    [lbl1 sizeToFit];

lbl2.text = @"World";
        [lbl2 sizeToFit];
        lbl2.frame = CGRectMake(lbl1.frame.origin.x+lbl1.frame.size.width+5,
                                lbl1.frame.origin.y,
                                lbl2.frame.size.width,
                                lbl1.frame.size.height);
3 голосов
/ 13 января 2010

Я нашел ту же проблему, но я нашел обходной путь. К вашему сведению, я поднял ошибку с Apple (идентификатор ошибки # 7535066). Lex, в вашем примере, если вы используете cell.font вместо textLabel.font, он должен работать, хотя вы получите предупреждение компилятора, поскольку это устаревший вызов метода. Я не уверен, что вы сможете увидеть детали ошибки, которую я поднял, поэтому я вставляю детали здесь:

iPhone SDK 3.1.2 (7D11) NSString UIKit Метод сложений sizeWithFont возвращает nil

РЕЗЮМЕ Я украшаю UITableViewCells в методе делегата UITableView:

  • (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath

Я хочу найти длину текста уже в ячейке, чтобы правильно отформатировать новое представление, поэтому я вызываю метод NSString UIKit Additions:

  • (CGSize) sizeWithFont: (UIFont *) шрифт constrainedToSize: (CGSize) размер

Когда я использую cell.textLabel.font для аргумента шрифта, он всегда возвращает пустой CGSize

Если я использую метод DEPRECATED, cell.font для аргумента, он возвращает значение CGSize, как и ожидалось.

ШАГИ ДЛЯ ВОСПРОИЗВОДСТВА 1. Создайте UITableViewController с TableView и заполните его некоторыми примерами данных. 2. В заглушенном методе cellForRowAtIndexPath после комментария // Установите ячейку и укажите, где заполняется cell.textLabel.text, укажите следующее:

  
 CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)];
 NSLog(@"cell frame: %f %f", size.width, size.height);

 CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)];
 NSLog(@"DEPRECATED cell frame: %f %f", size2.width, size2.height);

ОЖИДАЕМЫЕ РЕЗУЛЬТАТЫ

Во всяком случае, вы ожидаете, что вызов, использующий метод Устаревший, для извлечения шрифта, сбой или, по крайней мере, оба для возврата того же результата.

АКТУАЛЬНЫЙ РЕЗУЛЬТАТ:

2010-01-12 22: 06: 36.645 PrefTest [9659: 207] фрейм ячейки: 0,000000 0,000000 2010-01-12 22: 06: 36.646 PrefTest [9659: 207] УСТАРЕВШИЙ кадр ячейки: 88.000000 24.000000

ВРЕМЕННОЕ РЕШЕНИЕ И ИЗОЛЯЦИЯ:

Как уже отмечалось, используйте устаревший метод, чтобы получить шрифт. Но это становится незнакомым!

Поменяйте местами два приведенных выше метода:

 
 CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)];
 NSLog(@"DEPRECATED cell frame: %f %f", size2.width, size2.height);

    CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)];
 NSLog(@"cell frame: %f %f", size.width, size.height);

Результаты теперь:

2010-01-12 22: 06: 36.645 PrefTest [9659: 207] фрейм ячейки: 88.000000 24.000000 2010-01-12 22: 06: 36.646 PrefTest [9659: 207] УСТАРЕВШИЙ кадр ячейки: 88.000000 24.000000

Кажется, что простой ссылки на [шрифт ячейки] достаточно, чтобы заставить [[text textLabel] шрифт] работать правильно.

...