2010-11-28 3 views
1

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

Выглядит неплохо, за исключением случаев, когда я прокручиваю вверх и вниз, textLablels, аксессуары и дополнительные subviews начинают смещаться в разные rowss, и я не могу понять, почему.

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

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

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == kSection_Info && indexPath.row == kSectionRow_InfoPhoto) 
    { 
     return 84.0; 
    } 
    else if (indexPath.section == kSection_Level && indexPath.row == kSectionRow_LevelLevel) 
    { 
     return 70.0; 
    } 
    return 44.0; 
} 

Я настраиваю каждую строку вручную в celForRowAtIndexPath:

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     switch (indexPath.section) 
     { 
      case kSection_Info: 
      { 
       switch (indexPath.row) 
       { 
        case kSectionRow_InfoName: 
        { 
         cell.textLabel.text = @"Name"; 
         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
         self.nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(74, 8, 195, 25)]; 
         self.nameLabel.textAlignment = UITextAlignmentRight; 
         self.nameLabel.font = [UIFont systemFontOfSize:16]; 
         self.nameLabel.textColor = [UIColor blueColor]; 
         self.nameLabel.text = self.currentRecipient.fullName;      
         [cell.contentView addSubview:self.nameLabel]; 

         break; 
        } 
        case kSectionRow_InfoPhoto: 
        { 
         cell.textLabel.text = @"Photo"; 
         self.imageButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
         self.imageButton.frame = CGRectMake(10, 14, 64, 64); 
         [self.imageButton addTarget:self action:@selector(onImageButtonTouch:) forControlEvents:UIControlEventTouchUpInside];     

         NSString *imageName = @"add_image.png"; 
         UIImage *thumb = [UIImage imageNamed:imageName]; 
         [self.imageButton setImage:thumb forState:UIControlStateNormal]; 
         cell.accessoryView = self.imageButton; 

         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_List: 
      { 
       switch (indexPath.row) 
       { 
        case kSectionRow_ListHasList: 
        { 
         cell.textLabel.text = @"Is Listed";     
         self.listSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; 
         cell.accessoryView = self.listSwitch;     

         break; 
        } 
        case kSectionRow_ListBudget: 
        { 
         cell.textLabel.text = @"List Amount"; 
         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 
         self.budgetLabel = [[UILabel alloc] initWithFrame:CGRectMake(124, 8, 145, 25)]; 
         self.budgetLabel.textAlignment = UITextAlignmentRight; 
         self.budgetLabel.font = [UIFont systemFontOfSize:16]; 
         self.budgetLabel.textColor = [UIColor blueColor]; 
         self.budgetLabel.text = [@"$" stringByAppendingFormat:@"%0.2f", [self.currentRecipient.budget floatValue]];      
         [cell.contentView addSubview:self.budgetLabel]; 

         break; 
        } 
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_Level: 
      { 
       switch (indexPath.row) 
       {    
        case kSectionRow_LevelLevel: 
        { 
         self.levelSlider = [[UISlider alloc] initWithFrame:CGRectMake(8, 2, 284, 40)]; 
         self.levelSlider.minimumValue = 0.0; 
         self.levelSlider.maximumValue = 100.0; 
         self.levelSlider.continuous = YES; 

         UIImage *meterImage = [UIImage imageNamed:@"meter_labels.png"]; 
         UIImageView *meterView = [[UIImageView alloc] initWithFrame:CGRectMake(8, 32, 284, 24)]; 
         [meterView setImage:meterImage]; 

         [cell.contentView addSubview:self.levelSlider]; 
         [cell.contentView addSubview:meterView]; 
         [meterImage release]; 

         break; 
        } 
        case kSectionRow_LevelHasLevel: 
        { 
         cell.textLabel.text = @"Show Level"; 
         self.levelSwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease]; 
         cell.accessoryView = self.levelSwitch;        
         break; 
        }      
        default: 
        { 
         break; 
        } 
       } 
       break; 
      } 

      case kSection_RecipientDelete: 
      { 
       cell.textLabel.text = @"Delete Recipient";   
       cell.textLabel.textAlignment = UITextAlignmentCenter; 
       cell.textLabel.textColor = [UIColor blueColor];    
       break; 
      } 

      default: 
      { 
       break; 
      } 
     } 
    } 

    return cell; 
} 
+0

Как выглядит ваш метод tableView: cellForRowAtIndexPath: `? – 2010-11-28 20:35:59

+0

Добавил его на мой вопрос, спасибо! – bread 2010-11-28 21:46:47

ответ

0

«Содержание перетасовки» Вы видите, скорее всего, из-за неправильное обращение с сотовым повторным использованием.

Нет проблем конкретно с сгруппированным стилем. Проблема, скорее всего, проявится в этом стиле, потому что на экране появляется меньше ячеек, для чего требуется больше прокрутки и требуется больше повторного использования соты.

Вы создаете содержимое ячейки только при создании ячеек (когда cell == nil). Когда ячейка прокручивается с экрана, она переходит в очередь повторного использования. Строка с другого конца, которая теперь видна, повторно использует вид ячейки, который находится в очереди повторного использования. Повторно используемая ячейка содержит содержимое другой строки.

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


Потому что у вас есть только небольшое количество строк, и каждый из них уложены по-разному, быстрый (и, возможно, загрязнен) решение заключается в использовании другого повторного использования идентификатора для каждой ячейки, как это:

NSString *CellIdentifier = 
    [NSString stringWithFormat:@"RecipientEntryCell-%d-%d", 
    indexPath.section, indexPath.row]; 

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

Руководство по программированию таблиц показывает альтернативный способ создания табличных представлений, подобных этому, где у вас есть несколько ячеек с разными макетами. См. «Техника для содержимого Static Row» на странице this page.


В конечном счете, если вы понимаете, что представление таблицы повторно использует ячейки по уважительным причинам и не пытается обходить ее все время.Как правило, cellForRowAtIndexPath должен выглядеть следующим образом:

static NSString *CellIdentifier = @"CellIdentifier"; 

UITableViewCell *cell = [tableView dequeueReusableCell... 
if (cell == nil) { 
    //Create cell... 
    //Set UI content that applies to all rows (if any)... 
} 
else { 
    //Cell is being re-used. 
    //Remove UI content that doesn't apply to this row... 
} 

//Add UI content that applies only to this row... 

//Copy values from data source to cell UI controls... 

return cell; 

Если построить клетки, как было показано выше, не поддерживает ссылки уровня класса к элементам управления пользовательского интерфейса внутри клеток (например, nameLabel, IMAGEBUTTON и т.д.). Вместо этого контрольные значения должны быть установлены в cellForRowAtIndexPath из резервной переменной (модели) данных, и значение должно быть прочитано или сохранено обратно в переменную данных базы данных сразу после изменения элемента управления пользовательского интерфейса.

Например, вместо сохранения ссылки на UISlider в ячейке сохраните текущее значение ползунка в качестве ivar float. Инициализируйте поплавок, где это необходимо (например, viewDidLoad). В cellForRowAtIndexPath создайте UISlider, установите его значение с помощью float ivar и вызовите метод слайдера при изменении его значения. В этом методе скопируйте значение ползунка в float ivar.

Надеюсь, это поможет.

Смежные вопросы