iOS SDK дает нам «из коробки» два варианта настроить кнопку, которая будет показана при сдвиге UITableViewCell влево.
Первый вариант, доступный с первых версий и до наших дней, мало привлекателен для обычных кнопок, поскольку предназначен именно для «опасных» действий, ибо фон окрашивается системой в красный цвет и не поддается легкому изменению через публичный API.
Второй вариант, доступный с iOS 8, больше привлекает, поскольку есть возможность указать стиль кнопки (Destructive, Normal), а также в случае надобности установить конкретный цвет фона через backgroundColor.
Ни первый, ни второй варианты не дают возможности назначить иконку, что довольно неприятно.
Но мы всё равно попробуем что-нибудь сделать.
Попытка раз
UITableViewRowAction выглядит более богатым к настройке. Попробуем поставить ему backgroundColor с помощью patternImage:
Результат ожидаемо кривоват, но мы хотя бы получили иконку на кнопке.
Оставим вопрос цвета фона и текста на потом, сперва попробуем настроить саму иконку.
Попытка два
Поскольку patternImage призван повторяться, попробуем увеличить сам pattern, чтобы он повторялся поменьше — создадим pattern по размеру кнопки:
Теперь смотрится гораздо лучше. Но если, например, поле окажется многострочным, а следом по высоте растянется и ячейка, то будет не очень приятно:
Попытка три
Попробуем сделать иначе. Что происходит, когда мы сдвигаем строку влево? Верно, она просто уезжает левее, обнажая то, что находится ниже по иерархии: кнопку. Попробуем добавить слой сверху, который будет пристегнут к правому краю ячейки (компонент PureLayout в помощь для быстроты реализации).
Теперь результат гораздо приятнее, правда есть одно но в данном подходе: ширина сдвига ячейки определяется текстом в UITableViewRowAction.title. Соответственно, придется регулировать видимую часть кнопки именно этим параметром. Как вариант — заполнять его соответствующими нужной ширине пробелами, или дописывать что-то в начало или конец.
К слову, данный элемент не отрабатывает нажатия сам, поэтому они спокойно пересылаются в UITableViewRowAction.handler.
Попытка четыре
Похоже, теперь всё выглядит отлично.
В итоге есть два но при таком подходе:
— ширина сдвига определяется отдельно параметром UITableViewRowAction.title
— не получится сделать более одной кнопки, либо придется теснить их все в собственном слое и туда же вставлять свои кнопки
Однако это видится мне приятнее, чем распространенный подход по встраиванию кнопки в саму ячейку с обработкой жестов, поскольку усложняется логика.
Возможно, есть еще более лаконичный способ добиться желаемого, но мне о таком пока неизвестно.
Первый вариант, доступный с первых версий и до наших дней, мало привлекателен для обычных кнопок, поскольку предназначен именно для «опасных» действий, ибо фон окрашивается системой в красный цвет и не поддается легкому изменению через публичный API.
- (NSString *)tableView:(nonnull UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
return @"Настроить";
}
Второй вариант, доступный с iOS 8, больше привлекает, поскольку есть возможность указать стиль кнопки (Destructive, Normal), а также в случае надобности установить конкретный цвет фона через backgroundColor.
- (NSArray<UITableViewRowAction *> *)tableView:(nonnull UITableView *)tableView editActionsForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UITableViewRowAction *configureAction;
configureAction = [UITableViewRowAction
rowActionWithStyle:UITableViewRowActionStyleNormal
title:@"Настроить"
handler:^(UITableViewRowAction * __nonnull action, NSIndexPath * __nonnull indexPath) {
// handle
}];
return @[ configureAction ];
}
Ни первый, ни второй варианты не дают возможности назначить иконку, что довольно неприятно.
Но мы всё равно попробуем что-нибудь сделать.
Попытка раз
UITableViewRowAction выглядит более богатым к настройке. Попробуем поставить ему backgroundColor с помощью patternImage:
UIImage *patternImage = [UIImage imageNamed:@"gear_compact"]; // 50x50
configureAction.backgroundColor = [UIColor colorWithPatternImage:patternImage];
Результат ожидаемо кривоват, но мы хотя бы получили иконку на кнопке.
Оставим вопрос цвета фона и текста на потом, сперва попробуем настроить саму иконку.
Попытка два
Поскольку patternImage призван повторяться, попробуем увеличить сам pattern, чтобы он повторялся поменьше — создадим pattern по размеру кнопки:
UIImage *patternImage = [UIImage imageNamed:@"gear_fullsize"]; // 240x90
configureAction.backgroundColor = [UIColor colorWithPatternImage:patternImage];
Теперь смотрится гораздо лучше. Но если, например, поле окажется многострочным, а следом по высоте растянется и ячейка, то будет не очень приятно:
Попытка три
Попробуем сделать иначе. Что происходит, когда мы сдвигаем строку влево? Верно, она просто уезжает левее, обнажая то, что находится ниже по иерархии: кнопку. Попробуем добавить слой сверху, который будет пристегнут к правому краю ячейки (компонент PureLayout в помощь для быстроты реализации).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [UITableViewCell new];
cell.textLabel.text = self.objects[indexPath.row];
cell.textLabel.numberOfLines = 0;
UIView *actionView = [UIView new];
actionView.backgroundColor = [UIColor greenColor];
[cell addSubview:actionView];
[actionView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:cell];
[actionView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:cell];
[actionView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:cell];
[actionView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:cell.contentView];
UIImageView *actionIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"gear_compact"]];
[actionView addSubview:actionIcon];
[actionIcon autoAlignAxis:ALAxisHorizontal toSameAxisOfView:actionView];
[actionIcon autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:actionView withOffset:10];
UILabel *actionLabel = [UILabel new];
actionLabel.text = @"Настроить";
[actionView addSubview:actionLabel];
[actionLabel autoAlignAxis:ALAxisHorizontal toSameAxisOfView:actionView];
[actionLabel autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:actionIcon withOffset:5];
return cell;
}
Теперь результат гораздо приятнее, правда есть одно но в данном подходе: ширина сдвига ячейки определяется текстом в UITableViewRowAction.title. Соответственно, придется регулировать видимую часть кнопки именно этим параметром. Как вариант — заполнять его соответствующими нужной ширине пробелами, или дописывать что-то в начало или конец.
К слову, данный элемент не отрабатывает нажатия сам, поэтому они спокойно пересылаются в UITableViewRowAction.handler.
Попытка четыре
- (NSArray<UITableViewRowAction *> *)tableView:(nonnull UITableView *)tableView editActionsForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UITableViewRowAction *configureAction;
configureAction = [UITableViewRowAction
rowActionWithStyle:UITableViewRowActionStyleNormal
title:@"(i) Настроить"
handler:^(UITableViewRowAction * __nonnull action, NSIndexPath * __nonnull indexPath) {
// handle
}];
return @[ configureAction ];
}
Похоже, теперь всё выглядит отлично.
В итоге есть два но при таком подходе:
— ширина сдвига определяется отдельно параметром UITableViewRowAction.title
— не получится сделать более одной кнопки, либо придется теснить их все в собственном слое и туда же вставлять свои кнопки
Однако это видится мне приятнее, чем распространенный подход по встраиванию кнопки в саму ячейку с обработкой жестов, поскольку усложняется логика.
Возможно, есть еще более лаконичный способ добиться желаемого, но мне о таком пока неизвестно.
Комментарии (3)
blind_oracle
08.07.2015 13:35(NSString *)tableView:(nonnull UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
Название где-то за гранью добра и зла :)
Kirpa
Можно использовать или сторонние компоненты или посмотреть как у них работает. Вот один такой компонент, написаный моим коллегой. www.cocoacontrols.com/controls/afmslidingcell
На сайте есть и другие, если конкретная реализация не подходит.
bronenos Автор
В целом я это и имел в виду, когда писал про усложнение логики своими жестами и прочим.
Если же говорить об использовании компонента, то да, согласен, тоже вариант.
Да и в любом случае, эта статья – не документация, а просто вариант того, как можно справиться подручными средствами в случае необходимости.