UITableView: добавляем иконку в UITableViewRowAction

от автора

iOS SDK дает нам «из коробки» два варианта настроить кнопку, которая будет показана при сдвиге UITableViewCell влево.

Первый вариант, доступный с первых версий и до наших дней, мало привлекателен для обычных кнопок, поскольку предназначен именно для «опасных» действий, ибо фон окрашивается системой в красный цвет и не поддается легкому изменению через публичный 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]; 

image

Результат ожидаемо кривоват, но мы хотя бы получили иконку на кнопке.
Оставим вопрос цвета фона и текста на потом, сперва попробуем настроить саму иконку.


Попытка два

Поскольку patternImage призван повторяться, попробуем увеличить сам pattern, чтобы он повторялся поменьше — создадим pattern по размеру кнопки:

UIImage *patternImage = [UIImage imageNamed:@"gear_fullsize"]; // 240x90 configureAction.backgroundColor = [UIColor colorWithPatternImage:patternImage]; 

image

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

image


Попытка три

Попробуем сделать иначе. Что происходит, когда мы сдвигаем строку влево? Верно, она просто уезжает левее, обнажая то, что находится ниже по иерархии: кнопку. Попробуем добавить слой сверху, который будет пристегнут к правому краю ячейки (компонент 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; } 

image

Теперь результат гораздо приятнее, правда есть одно но в данном подходе: ширина сдвига ячейки определяется текстом в 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 ]; } 

image

Похоже, теперь всё выглядит отлично.

В итоге есть два но при таком подходе:
— ширина сдвига определяется отдельно параметром UITableViewRowAction.title
— не получится сделать более одной кнопки, либо придется теснить их все в собственном слое и туда же вставлять свои кнопки

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

Возможно, есть еще более лаконичный способ добиться желаемого, но мне о таком пока неизвестно.

ссылка на оригинал статьи http://habrahabr.ru/post/261905/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *