Сгруппированные строки UITableView с различной высотой вызывают перемешивание содержимого - PullRequest
1 голос
/ 28 ноября 2010

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

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

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

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

- (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;
}

1 Ответ

0 голосов
/ 07 декабря 2010

«Перестановка контента», которую вы видите, наиболее вероятна из-за неправильной обработки повторного использования ячейки.

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

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

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


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

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

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

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


В конечном счете, лучше понять, что табличное представление повторно использует ячейки по уважительным причинам, а не пытаться все время обходить их. Как правило, 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 из резервной переменной данных (модель), а значение должно быть прочитано или сохранено обратно в резервную переменную данных, как только элемент управления UI изменится.

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

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

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