Изменения UITableView cell.contentView.bounds.size.width при повторном использовании ячеек
Я использую cell.contentView.bounds.size.width
для вычисления положения текстового поля в ячейке UITableView. Когда ячейка создана, отладочный код сообщает ширину как 302. Когда ячейка прокручивается с экрана, а затем возвращается, код отладки сообщает, что он равен 280 - каждый раз. Кажется, он не хочет возвращаться к 302 и остается застрявшим до 280. Конечным результатом является то, что текстовое поле попадает не в то место во второй раз, когда поле помещается в содержимое cellView, хотя оно помещено в правое место в первый раз.
Я цифра 22 как-то значительна, но я не знаю, что это такое. Угадав, что это может быть стрелка раскрытия, я переместил код "очистить ячейку" перед определением ширины, включая установку аксессуара на наду.
Кто-нибудь может сказать мне, что здесь происходит?
Код (с нерелевантным - что я знаю - вырезанный материал) выглядит следующим образом:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
while( [cell.contentView.subviews count] ){
id subview = [cell.contentView.subviews objectAtIndex:0];
[subview removeFromSuperview];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
8< snip!
CGFloat theCellWidth = cell.contentView.bounds.size.width - 44.0;
CGFloat theLineHeight = [[UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0] lineHeight];
NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
if (0==section) {
switch (row) {
case 2:
while( [cell.contentView.subviews count] ){
id subview = [cell.contentView.subviews objectAtIndex:0];
[subview removeFromSuperview];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = @" ";
cell.detailTextLabel.text = @"The Age";
theAgeTextField.frame = CGRectMake(10.0, 2.0, theCellWidth, theLineHeight);
// NSLog(@"cell.contentView %@",cell.contentView);
theAgeTextField.text = theAge;
theAgeTextField.font = [UIFont boldSystemFontOfSize: [UIFont labelFontSize]+1.0];
theAgeTextField.keyboardType = UIKeyboardTypeDecimalPad;
theAgeTextField.borderStyle = UITextBorderStyleNone;
theAgeTextField.userInteractionEnabled = NO;
[cell.contentView addSubview:theAgeTextField];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
8< snip! (lots of closing braces and other stuff omitted)
return cell;
}
Хотите попробовать это дома, мальчики и девочки?
Начните с нового навигационного приложения. Поместите следующий код в RootViewController.m:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(@"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
// Configure the cell.
return cell;
}
Для кода этого кода требуется всего два изменения кода: изменение количества строк в разделе ( "возврат 5" ), а стиль ячейки должен быть UITableViewCellStyleSubtitle. Затем, когда вы запустите программу, вы увидите пять строк этого:
2011-06-18 11:10:19.976 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.978 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.979 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.980 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
2011-06-18 11:10:19.982 TestTableCells[7569:207] cell.contentView.bounds.size.width 302
Перетащите некоторые ячейки с экрана (перетащить вверх - ничего не делает), и когда они снова появятся, вы получите следующее:
2011-06-18 11:10:24.013 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.047 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
2011-06-18 11:10:24.130 TestTableCells[7569:207] cell.contentView.bounds.size.width 320
Честно говоря, я расстроен, как черт с этим, и мне так очень хочется поднять $99 (без рабочего приложения, даже), поэтому я могу заставить кого-то в Apple взвесить на этом.
У кого-нибудь есть идеи, что здесь происходит?
Спасибо!
Хотите увидеть что-то более интересное? Попробуйте это вместо строки static NSString...
:
NSString *CellIdentifier = [NSString stringWithFormat: @"%d", arc4random() ];
NSLog(@"%@",CellIdentifier);
Теперь каждый раз ширина в журнале всегда равна 302. Казалось бы, что повторно используемая ячейка имеет разную ширину содержимого, чем исходная ячейка.
Опять... интересно... кто-нибудь понял?
Ответы
Ответ 1
Я подозреваю, что то, что вы видите, связано с изменением вида сотового аксессуара, который в конечном итоге изменит размер представления содержимого в следующий раз, когда ячейка выполнит -layoutSubviews
. Это должно произойти, когда ячейка добавляется в таблицу, но до тех пор границы представления содержимого не будут обновляться.
Несмотря на это, я не понимаю, почему это было проблемой. Кажется, что вы занимаетесь только настройкой ширины вашего theAgeTextField
, поэтому, если вы соответствующим образом определяете ее по отношению к текущей ширине представления содержимого и устанавливаете ее флаги autoresizingMask
, чтобы дать ей гибкую ширину, тогда она должна расти или уменьшаться по мере необходимости, когда границы представления содержимого меняются.
Если вам требуется более подробное поведение макета, это, вероятно, должно произойти в подклассе UITableViewCell
. См. -prepareForReuse
и -layoutSubviews
для возможности настройки ячейки и ее подзонов. Ваш источник данных должен иметь возможность просто передать theAge
в экземпляр вашего подкласса ячейки и не учитывать детали того, как это будет отображаться.
Ответ 2
Я столкнулся с тем же, за исключением того, что смещение было 20 вместо 22. Я думаю, что ответ Джона на правильном пути, но для быстрого обходного пути, который позволяет избежать изменения размера cell.contentView.frame/bounds, я просто использовал cell.frame/bounds как моя ссылка для выделения представлений в содержимом cellView.
Ответ 3
Вы должны реализовать высоту для метода делегата строки и выполнить все ваши вычисления там
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// do math
return newheight;
}
Это даст вам то, что вам нужно, у вас также есть доступ к указательному пути, поэтому вы можете легко найти строку в своем массиве и сделать все, что вам нужно, иначе вы получите размер повторно используемой строки из очереди, который всегда является размером строки по умолчанию.