UITableViewRowAction image for title

I made a custom UITableViewRowAction. Now I would like to add an image instead of text. I know that this is possible, but I do not know how to do it. Do any of you know how to do this in Swift and would like to help me? Thank you for your responses!

+29
ios uitableview swift xcode6 uitableviewrowaction
Apr 02 '15 at 20:29
source share
8 answers

iOS 11.0

Apple introduced a flexible way to announce a series of actions with great benefits.

extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let askAction = UIContextualAction(style: .normal, title: nil) { action, view, complete in print("Ask!") complete(true) } // here set your image and background color askAction.image = IMAGE askAction.backgroundColor = .darkGray let blockAction = UIContextualAction(style: .destructive, title: "Block") { action, view, complete in print("Block") complete(true) } return UISwipeActionsConfiguration(actions: [blockAction, askAction]) } func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { cell.textLabel?.text = "row: \(indexPath.row)" } } 

Example:

enter image description here

iOS 8.0

You need to set the UIImage for the backgroundColor action of the string, specifically:

Swift:

 UIColor(patternImage: UIImage(named: "IMAGE_NAME")) 

Objective-C:

 [UIColor colorWithPatternImage:[UIImage imageNamed:@"IMAGE_NAME"]]; 
+40
Apr 02 '15 at 20:48
source share
— -

Swift 4 (iOS 11+):

iOS 11 now supports images (only) for display in action buttons. You just need to initialize the UISwipeActionsConfiguration object in the table view delegate object:

 extension MyTableViewController:UITableViewDelegate { func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { let deleteAction = UIContextualAction(style: .normal, title: nil, handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in debugPrint("Delete tapped") success(true) }) deleteAction.image = UIImage(named: "icon_delete.png") deleteAction.backgroundColor = UIColor.red return UISwipeActionsConfiguration(actions: [deleteAction]) } 

}

+7
Jul 03 '18 at 11:09
source share

I made this simple UITableViewRowAction category to set an icon for my actions. You can set the image, background color, cell height (for managing dynamic cells) and icon size in percent.

 extension UITableViewRowAction { func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, iconSizePercentage: CGFloat) { let iconHeight = cellHeight * iconSizePercentage let margin = (cellHeight - iconHeight) / 2 as CGFloat UIGraphicsBeginImageContextWithOptions(CGSize(width: cellHeight, height: cellHeight), false, 0) let context = UIGraphicsGetCurrentContext() backColor.setFill() context!.fill(CGRect(x:0, y:0, width:cellHeight, height:cellHeight)) iconImage.draw(in: CGRect(x: margin, y: margin, width: iconHeight, height: iconHeight)) let actionImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); self.backgroundColor = UIColor.init(patternImage: actionImage!) } } 
+6
Jan 05 '18 at 22:32
source share
 class TableViewRowAction: UITableViewRowAction { var image: UIImage? func _setButton(button: UIButton) { if let image = image, let titleLabel = button.titleLabel { let labelString = NSString(string: titleLabel.text!) let titleSize = labelString.sizeWithAttributes([NSFontAttributeName: titleLabel.font]) button.tintColor = UIColor.whiteColor() button.setImage(image.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal) button.imageEdgeInsets.right = -titleSize.width } } } func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? { let delete = TableViewRowAction(style: UITableViewRowActionStyle.Default, title: " ") { action, indexPath in } delete.image = UIImage(named: "trashImg") let sharing = TableViewRowAction(style: UITableViewRowActionStyle.Default, title: " ") { action, indexPath in } sharing.backgroundColor = UIColor.lightGrayColor() sharing.image = UIImage(named: "sharingImg") return [delete, sharing] } 
+5
Jul 29 '16 at 9:58
source share

I am just implementing the best version of https://stackoverflow.com/a/166329/1209.jpg 1. In most cases, the cell height and width of the custom swipe part are different, you should calculate this in your function 2. The image may have a different size than a square, so you must calculate proportions not only in height. So, the code with my corrections

 func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, customSwipPartWidth: CGFloat, iconSizePercentage: CGFloat) { let iconWidth = customSwipPartWidth * iconSizePercentage let iconHeight = iconImage.size.height / iconImage.size.width * iconWidth let marginY = (cellHeight - iconHeight) / 2 as CGFloat let marginX = (customSwipPartWidth - iconWidth) / 2 as CGFloat UIGraphicsBeginImageContextWithOptions(CGSize(width: customSwipPartWidth, height: cellHeight), false, 0) let context = UIGraphicsGetCurrentContext() backColor.setFill() context!.fill(CGRect(x:0, y:0, width:customSwipPartWidth, height:cellHeight)) iconImage.draw(in: CGRect(x: marginX, y: marginY, width: iconWidth, height: iconHeight)) let actionImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); self.backgroundColor = UIColor.init(patternImage: actionImage!) } 
+1
May 08 '18 at 13:16
source share
 delActions.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"delete.png"]]; 
0
Oct 09 '15 at 13:13
source share

The problem with the basic approach to the template is that your image should be the same size as the action button, or at least have a flatter background at the bottom to prevent the image from repeating (although this will be snapped on top, which doesn't very nice).

I had to deal with dynamic height cells, so I implemented the following:

 - (UIColor *)backgroundImageForActionAtIndexPath:(NSIndexPath *)indexPath withImage:(UIImage *)image tintColor:(UIColor *)tintColor backgroundColor:(UIColor *)backgrounfColor expectedWith:(CGFloat)width { // CGRect cellFrame = [self.tableView rectForRowAtIndexPath:indexPath]; CGSize expectedSize = CGSizeMake(width, cellFrame.size.height); UIGraphicsBeginImageContextWithOptions(expectedSize, NO, 0.0); CGContextRef ctx = UIGraphicsGetCurrentContext (); if (ctx) { // set the background CGContextSetFillColorWithColor(ctx, backgrounfColor.CGColor); CGRect fillRect = CGRectZero; fillRect.size = expectedSize; CGContextFillRect(ctx, fillRect); // put the image CGContextSetFillColorWithColor(ctx, tintColor.CGColor); CGRect rect = CGRectMake((expectedSize.width - image.size.width) / 2., (expectedSize.height - image.size.height) / 2., image.size.width, image.size.height); [image drawInRect:rect]; } UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return [UIColor colorWithPatternImage:newImage]; 

}

You still need to set the expected width so that it matches the empty label marked in the action header. for example: @ "" → 64.f

As you can see with this approach, you can set the background color of the button and the hue in the code, and not in the work of art itself.

0
Dec 01 '17 at 16:22
source share

My option is trying to use the UImageView contentMode behavior, and when that was not enough, I found a good use for a pair of Core Geometry Rect methods, since they hold the target frame in the center of the cell frame. Using a vision check, it seems that swiping removed half of my normal cell width, so where the magic numbers appear.

Swift 3.0

 extension UITableViewRowAction { func setIcon(iconImage: UIImage, backColor: UIColor, cellHeight: CGFloat, cellWidth:CGFloat) ///, iconSizePercentage: CGFloat) { let cellFrame = CGRect(origin: .zero, size: CGSize(width: cellWidth*0.5, height: cellHeight)) let imageFrame = CGRect(x:0, y:0,width:iconImage.size.width, height: iconImage.size.height) let insetFrame = cellFrame.insetBy(dx: ((cellFrame.size.width - imageFrame.size.width) / 2), dy: ((cellFrame.size.height - imageFrame.size.height) / 2)) let targetFrame = insetFrame.offsetBy(dx: -(insetFrame.width / 2.0), dy: 0.0) let imageView = UIImageView(frame: imageFrame) imageView.image = iconImage imageView.contentMode = .left guard let resizedImage = imageView.image else { return } UIGraphicsBeginImageContextWithOptions(CGSize(width: cellWidth, height: cellHeight), false, 0) guard let context = UIGraphicsGetCurrentContext() else { return } backColor.setFill() context.fill(CGRect(x:0, y:0, width:cellWidth, height:cellHeight)) resizedImage.draw(in: CGRect(x:(targetFrame.origin.x / 2), y: targetFrame.origin.y, width:targetFrame.width, height:targetFrame.height)) guard let actionImage = UIGraphicsGetImageFromCurrentImageContext() else { return } UIGraphicsEndImageContext() self.backgroundColor = UIColor.init(patternImage: actionImage) } } 

Usage: from the editActions ... method of a tableview delegate.

 let cellHeight = (self.tableView(tableView, cellForRowAt: indexPath)).frame.size.height let cellWidth = (self.tableView(tableView, cellForRowAt: indexPath)).frame.size.width let favorite = UITableViewRowAction(style: .normal, title: nil) { action, index in //perform action debugPrint("Test") } favorite.setIcon(iconImage: #imageLiteral(resourceName: "favorite"), backColor: .green, cellHeight: cellHeight, cellWidth:cellWidth) 
0
Dec 12 '18 at 5:13
source share



All Articles