UITableViewRowAction image for title
Solution 1
iOS 11.0
Swift
Apple introduced flexible way to declare row 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:
iOS 8.0
You need to set UIImage to backgroundColor of row action, concretely by:
Swift:
UIColor(patternImage: UIImage(named: "IMAGE_NAME"))
Objective-C:
[UIColor colorWithPatternImage:[UIImage imageNamed:@"IMAGE_NAME"]];
Solution 2
Swift 4 (iOS 11+):
iOS 11 now supports images (only) to display in action buttons. You simply have to initialize a UISwipeActionsConfiguration object in your 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])
}
}
Solution 3
I made this simple UITableViewRowAction category, in order to set the icon for my actions. You can set the image, the background color, the cell height (to manage dynamic cells) and the icon size in percentage.
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!)
}
}
Solution 4
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]
}
Solution 5
For those who want to create this effect;
I have created an extension for UISwipeActionsConfiguration
which you can use without any third-party library. Basically, the idea is to create an Attributed String from the image and the text and set it to label and create an image from that label. And append it to UIContextualAction
's image
property.
extension UISwipeActionsConfiguration {
public static func makeTitledImage(
image: UIImage?,
title: String,
textColor: UIColor = .white,
font: UIFont = .systemFont(ofSize: 14),
size: CGSize = .init(width: 50, height: 50)
) -> UIImage? {
/// Create attributed string attachment with image
let attachment = NSTextAttachment()
attachment.image = image
let imageString = NSAttributedString(attachment: attachment)
/// Create attributed string with title
let text = NSAttributedString(
string: "\n\(title)",
attributes: [
.foregroundColor: textColor,
.font: font
]
)
/// Merge two attributed strings
let mergedText = NSMutableAttributedString()
mergedText.append(imageString)
mergedText.append(text)
/// Create label and append that merged attributed string
let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
label.textAlignment = .center
label.numberOfLines = 2
label.attributedText = mergedText
/// Create image from that label
let renderer = UIGraphicsImageRenderer(bounds: label.bounds)
let image = renderer.image { rendererContext in
label.layer.render(in: rendererContext.cgContext)
}
/// Convert it to UIImage and return
if let cgImage = image.cgImage {
return UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
}
return nil
}
}
And you can use it like this;
public func tableView(
_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath
) -> UISwipeActionsConfiguration?
{
let deleteAction = UIContextualAction(
style: .normal,
title: nil,
handler: { [weak self] (_, _, success: (Bool) -> Void) in
success(true)
print("Your action in here")
}
)
deleteAction.image = UISwipeActionsConfiguration.makeTitledImage(
image: UIImage(named: "delete_icon"),
title: "Delete")
)
deleteAction.backgroundColor = .orange
return UISwipeActionsConfiguration(actions: [deleteAction])
}
user3592462
Updated on April 09, 2021Comments
-
user3592462 about 3 years
I made a custom UITableViewRowAction. Now I'd like to add an image instead of the text. I know that it's possible but don't know how to do it. Does someone of you knows how to do this in Swift and would like to help me? Thanks for your answers!