Как реализовать multi-selection в UITableView?
Ответ
По умолчанию, UITableView поддерживает режим выбора только одной строки. Но можно создать свой multi-selection в UITbaleView. Чтобы таблица имела возможность множественного выбора нужно поставить стиль стандартного выделения "none" и самостоятельно отслеживать события и менять вид элементов. Для этого следует выполнить несколько шагов:
Пусть на верхней панели таблицы есть кнопка "Edit", которая при переходе в edit-mode меняется на "Cancel". При переходе в режим редактирования снизу таблицы появляется панель инструментов с вариантами действий над элементами таблицы.
Для обнаружения выделенных строк использовать метод tableView:didSelectRowAtIndexPath:. В этом методе мы будем добавлять только что выбранный элемент в коллекцию. Т.к. мы не можем полагаться на стандартный UITableView, мы должны создать коллекцию, содержащую выделенные в данный момент элементы. Также, при выборе элемента мы должны сменить фон элемента и отодвинуть его от левого края, чтобы поместить туда специальный индикатор выделения (наподобие checkbox).
Панель инструментов нужно создать в методе viewDidLoad, добавив что-то подобное:
actionToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 416, 320, 44)];
actionButton =
[[[UIBarButtonItem alloc]
initWithTitle:@"No Action"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(noAction:)]
autorelease];
[actionToolbar setItems:[NSArray arrayWithObject:actionButton]];
Затем, в методе viewDidAppear мы можем добавить нашу панель инструментов в иерархию
- (void)viewDidAppear:(BOOL)animated {
[self.view.superview addSubview:actionToolbar];
}
Стандартный режим редактирования для UITableView реализуется посредством вызова setEditing:animated:. Но т.к. Мы не собираемся использовать никакой из стандартных UITableViewCellEditingStyle, то вызов этого метода не является строго обязательным, но его можно будет использовать для уведомления UITableViewCell. Методы edit и cancel можно реализовать примерно так:
- (void)edit:(id)sender {
[self showActionToolbar:YES];
UIBarButtonItem *cancelButton =
[[[UIBarButtonItem alloc]
initWithTitle:@"Cancel"
style:UIBarButtonItemStyleDone
target:self
action:@selector(cancel:)]
autorelease];
[self.navigationItem setRightBarButtonItem:cancelButton animated:NO];
[self updateSelectionCount];
[self.tableView setEditing:YES animated:YES];
}
- (void)cancel:(id)sender {
[self showActionToolbar:NO];
UIBarButtonItem *editButton =
[[[UIBarButtonItem alloc]
initWithTitle:@"Edit"
style:UIBarButtonItemStylePlain
target:self
action:@selector(edit:)]
autorelease];
[self.navigationItem setRightBarButtonItem:editButton animated:NO];
NSInteger row = 0;
for (MultiSelectCellController *cellController in
[tableGroups objectAtIndex:0]) {
[cellController clearSelectionForTableView:self.tableView
indexPath:[NSIndexPath indexPathForRow:row inSection:0]];
row++;
}
[self.tableView setEditing:NO animated:YES];
}
Далее, при вызове setEditing у UITableView таблица вызывает setEditing у всех видимых элементов (UITableViewCell). Мы можем переопределить этот метод и использовать для перехода из режима в режим отдельно взятого элемента таблицы (показать или скрыть "галочку"). Проще всего это реализовать следующим образом: конкретно в методе setEditing мы инициируем relayout методом setNeedsLayout, а основной код поместим в layoutSubviews (теперь мы будем правильно перерисовывать элемент вне зависимости от того, что стало причиной перерисовки).
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[self setNeedsLayout];
}
Можно непосредственно в layoutSubviews и добавлять сам рисунок "галочки". Но с точки зрения организации кода это не очень красивое решение, т.к. подразумевается, что UITableViewCell - это только макет элемента. Поэтому лучше добавлять галочку уже в UITableView, но это неважно. Итак, в layoutSubviews мы будем отодвигать элемент от левого края, чтобы освободить место для "галочки", вот так:
- (void)layoutSubviews {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[super layoutSubviews];
if (((UITableView *)self.superview).isEditing) {
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 40; // делаем отступ
self.contentView.frame = contentFrame;
} else {
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 0;
self.contentView.frame = contentFrame;
}
[UIView commitAnimations];
}
Теперь осталось только поставить
cell.selectionStyle = UITableViewCellSelectionStyleNone
т.к. мы не хотим использовать стандартный selection. Вместо этого надо просто менять backgroundView у элемента.
P.s. Пример можно посмотреть в приложении Mail.
Комментариев нет:
Отправить комментарий