📜 ⬆️ ⬇️

UITableView: add icon to UITableViewRowAction

The iOS SDK gives us out of the box two options to configure the button that will be shown when UITableViewCell is shifted to the left.




The first option , available from the first versions to the present day, is not very attractive for ordinary buttons, since it is designed specifically for “dangerous” actions, because the background is colored by the system red and cannot be easily changed via the public API.
')
- (NSString *)tableView:(nonnull UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { return @""; } 


The second option , available with iOS 8, attracts more, since it is possible to specify the button style (Destructive, Normal), as well as, if necessary, set a specific background color via 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 ]; } 


Neither the first nor the second options make it impossible to assign an icon, which is quite unpleasant.
But we still try to do something.



Attempt once

UITableViewRowAction looks richer to customize. Let's try to set it to backgroundColor using patternImage :

 UIImage *patternImage = [UIImage imageNamed:@"gear_compact"]; // 50x50 configureAction.backgroundColor = [UIColor colorWithPatternImage:patternImage]; 

image

The result is expectedly crooked, but at least we got an icon on the button.
Let's leave the question of the color of the background and text for later, first try to customize the icon itself.



Attempt two

Since the patternImage is intended to repeat itself, we will try to increase the pattern itself so that it repeats less - we will create a pattern to fit the button:

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

image

Now it looks much better. But if, for example, the field turns out to be multi-line, and then the cell will also stretch along the height, it will not be very pleasant:

image



Attempt three

Let's try to do otherwise. What happens when we shift the string to the left? True, she just leaves to the left, exposing what is below the hierarchy: the button. Let's try to add a layer on top, which will be fastened to the right edge of the cell (the PureLayout component helps to speed up the implementation).

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

Now the result is much nicer, though there is one thing in this approach: the width of the cell shift is determined by the text in UITableViewRowAction.title. Accordingly, it is necessary to adjust the visible part of the button with this parameter. As an option - fill it with the appropriate width of the gap, or append something to the beginning or end.

By the way, this element does not work out pressing itself, so they are calmly sent to UITableViewRowAction.handler .



Attempt four

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

Looks like it looks great now.

As a result, there are two, but with this approach:
- the shift width is determined separately by the parameter UITableViewRowAction.title
- you will not be able to make more than one button, or you will have to crowd them all in your own layer and insert your own buttons there

However, it seems to me more pleasant than the common approach to embedding a button in the cell itself with gesture processing, since the logic is complicated.

Perhaps there is a more concise way to achieve the desired, but I still do not know about this.

Source: https://habr.com/ru/post/261905/


All Articles