UITableView, возникают проблемы при смене аксессуара при выборе - PullRequest
0 голосов
/ 10 июня 2009

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

Подкласс UIViewController - это делегат и источник данных моей таблицы (не UITableViewController, потому что там у меня также есть панель инструментов).

Я устанавливаю accessoryType ячеек в cellForRowAtIndexPath: и обновляю свою модель, когда ячейки выбраны в didSelectRowAtIndexPath :. Единственный способ установить галочку в выбранной ячейке (и очистить предыдущую) - это вызвать [tableView reloadData] в didSelectRowAtIndexPath :. Однако, когда я делаю это, анимация отмены выбора ячейки становится странной (появляется белая рамка там, где должна быть метка ячейки). Конечно, если я не вызову reloadData, accessoryType не изменится, поэтому галочки не появятся.

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

Есть идеи? Сокращенный код следует ...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell* aCell = [tableView dequeueReusableCellWithIdentifier:kImageCell];
    if( aCell == nil ) {
        aCell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:kImageCell];
    }

    aCell.text = [imageNames objectAtIndex:[indexPath row]];
    if( [indexPath row] == selectedImage ) {
        aCell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        aCell.accessoryType = UITableViewCellAccessoryNone;
    }
    return aCell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    selectedImage = [indexPath row]
    [tableView reloadData];
}

Ответы [ 7 ]

8 голосов
/ 18 июня 2009

Я решил это так, как предлагал шляпник в его правке. В моем примере кода проверяется только одна строка, но я уверен, что вы можете настроить ее, если это не то, что вам нужно.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

int newRow = [indexPath row];
int oldRow = [lastIndexPath row];

if (newRow != oldRow)
{
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:
                                indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:
                                lastIndexPath];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    lastIndexPath = indexPath;
}

[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
4 голосов
/ 13 июня 2009

У меня была точно такая же проблема, и я никогда ее не решал.

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

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

Тем не менее, не очень, и, если бы ребята из рингтона в Apple должны были сделать это таким образом, им следовало бы сильнее подтолкнуть команду UITableView, чтобы это исправить!

EDIT:

Ну, что ты знаешь ?! Это действительно легко в конце концов. - [UITableView cellForRowAtIndexPath] даст вам фактические ячейки (или ноль, если они находятся за пределами экрана), и вы можете просто изменить accessoryType.

2 голосов
/ 04 декабря 2010

Я использую этот простой и удобный рабочий механизм с reloadRowsAtIndexPaths.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSArray *rowsArray = [NSArray arrayWithObjects:indexPath, selectedIndexPath, nil];
    self.selectedIndexPath = indexPath;

    [tableView reloadRowsAtIndexPaths:rowsArray withRowAnimation:UITableViewRowAnimationNone];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    .... skipped usual code .....

    if ([selectedIndexPath compare:indexPath] == NSOrderedSame) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}
2 голосов
/ 15 августа 2010

У меня есть более чистый способ сделать это.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;

    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
}
1 голос
/ 27 октября 2010

Это будет работать как нужно ...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {


int newRow = [indexPath row];
int oldRow = [lastIndexPath row];


if (newRow == oldRow){
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;

    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

     lastIndexPath = indexPath;
}


if (newRow != oldRow)
{
    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
    newCell.accessoryType = UITableViewCellAccessoryCheckmark;

    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
    oldCell.accessoryType = UITableViewCellAccessoryNone;

    lastIndexPath = indexPath;
}


[tableView deselectRowAtIndexPath:indexPath animated:YES];

}
0 голосов
/ 12 августа 2011

Нашел ответ в другой теме здесь на SOF, работает как шарм: iPhone: UITableView CellAccessory Checkmark

0 голосов
/ 13 мая 2011
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:index];
    oldCell.accessoryType = UITableViewCellAccessoryNone;
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    index = indexPath;  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...