Автоматическое изменение размера UILabels в UITableViewCell - PullRequest
3 голосов
/ 23 февраля 2011

Я добавляю свои UILabel s к contentView из UITableViewCell, потому что мне нужно больше контроля над макетом, чем обеспечивает UITableViewCellStyles по умолчанию. По сути, я хочу, чтобы detailLabel имел приоритет над textLabel, поэтому textLabel усекается.

В моем UITableViewController есть следующий код:

- (UITableViewCell *)tableView:(UITableView *)tableView
  cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  static NSString * const kCellIdentifier = @"CustomCell";

  UITableViewCell * cell =
      [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];

  UILabel * titleLabel, * dateLabel;

  if(cell == nil)
  {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
        reuseIdentifier:kCellIdentifier] autorelease];

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    titleLabel = [[[UILabel alloc] init] autorelease];
    titleLabel.tag = kTitleLabelTag;
    titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;

    dateLabel = [[[UILabel alloc] init] autorelease];
    dateLabel.tag = kDateLabelTag;
    dateLabel.textColor = [UIColor blueColor];
    dateLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;

    [cell.contentView addSubview:titleLabel];
    [cell.contentView addSubview:dateLabel];
  }

  [self configureCell:cell atIndexPath:indexPath];
  return cell;
}

- (void)configureCell:(UITableViewCell *)pCell
  atIndexPath:(NSIndexPath *)pIndexPath
{
  const float kHeight = 44.0, kLeftIndent = 8.0, kOverallWidth = 293.0,
      kGap = 1.0;

  UILabel * titleLabel, * dateLabel;
  titleLabel = (UILabel *)[pCell.contentView viewWithTag:kTitleLabelTag];
  dateLabel = (UILabel *)[pCell.contentView viewWithTag:kDateLabelTag];

  NSString * dateText = @"9:39 AM";

  // Calculate the size of dateLabel
  CGSize dateSize = [dateText sizeWithFont:[dateLabel font]
      constrainedToSize:CGSizeMake(kOverallWidth, kHeight)];

  const float dateXPos = kOverallWidth - dateSize.width;
  dateLabel.frame = CGRectMake(dateXPos, 0.0, dateSize.width, kHeight);
  titleLabel.frame = CGRectMake(kLeftIndent, 0.0,
      dateXPos - kLeftIndent - kGap, kHeight);

  titleLabel.text = @"Some potentially very long text which will be wrapped.";
  dateLabel.text = dateText;
  pCell.contentView.backgroundColor = [UIColor purpleColor];
}

Код выше дает неправильные результаты. Когда табличное представление первоначально показано, оно выглядит как на рисунке 1) в это изображение визуализации .

Таким образом, нежелательный пробел справа от всех dateLabel s. (фиолетовый фон просто для лучшей видимости происходящего)

При перетаскивании вида таблицы вверх, как в 2) на изображении, он затем отскакивает назад и выглядит как 3).

Первая строка теперь имеет именно тот макет, который я хотел и который рассчитан в configureCell:atIndexPath:. Я предполагаю, что это происходит потому, что ячейки используются повторно, а затем снова настраиваются.

Так что я чувствую, что мне не хватает какой-то инициализации, я пытался вызвать setNeedsLayout и layoutSubviews из pCell и pCell.contentView, но никогда не достиг первоначального правильного рендеринга.

Только когда я установил autoresizingMask из titleLabel и dateLabel в UIViewAutoresizingNone, я получаю правильный начальный рендеринг, тогда, однако, удаление пальцем не работает, потому что кнопка удаления обрабатывается поверх dateLabel .

Что я должен изменить в своем коде, чтобы все ячейки отображались изначально , как первая ячейка на третьем рисунке?

Спасибо!

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

Ответы [ 2 ]

3 голосов
/ 23 февраля 2011

Хороший и, возможно, более простой способ сделать это:

Сначала создайте пользовательский подкласс UITableViewCell, который вы можете настроить с помощью Interface Builder. Если «MyTableViewCell» является вашим пользовательским представлением ячейки, вы инициализируете его в CellForRowAtIndexPath следующим образом:

MyTableViewCellClass *cell = (MyTableViewCellClass *)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCellClass"] autorelease];

if (!cell)
cell = [[[MyTableViewCellClass alloc] initWithStyle:UITableViewCellStyleDefault   reuseIdentifier:@"MyTableViewCellClass"] autorelease];

// Call specific methods on your cell to pass information to it, not for display
[cell setProperties:...];

Затем реализуйте метод layoutSubviews в своем пользовательском подклассе UITableViewCell. Например:

-(void) layoutSubviews
{
// You must call this first to make sure your cell gets current parent information
[super layoutSubviews];

// Retrieve the content view bounds. This will include the edit symbols when present (delete button and ordering symbol
float inset = 5.0;
CGRect bounds = [[self contentView] bounds];

// Keep on going here with your own view layout.

}

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

1 голос
/ 22 сентября 2014

Если вы работаете с раскадровкой , вам следует отключить «Использовать автоматическое расположение» в Инспекторе файлов!

Затем установите свойство ячейки autoresizesSubviews

- (void)awakeFromNib
{
    // Initialization code
    self.autoresizesSubviews=YES;

}

Последний шаг - настройка фрейма Label с переопределением метода layoutSubviews класса UITableViewCell

-(void)layoutSubviews{

    [super layoutSubviews];
    CGFloat top=VerticalPadding;
    CGFloat left=HorizentalPadding;
    CGFloat width=CGRectGetWidth(self.frame)-2*HorizentalPadding;
    CGFloat height=CGRectGetHeight(self.frame)-2*VerticalPadding;
    CGRect rect=CGRectMake(left, top, width, height);
    self.Label.frame=rect;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...