UITableViewRowAction with icon and text
What I ended up doing was generating an image on the fly as the background. This required the use of a hack/clever-trick or two.
The first part is the standard delegate method:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let stockWidth = String(repeating: " ", count: 8)
let rename = UITableViewRowAction(style: .normal, title: stockWidth) { (_, indexPath) in
self.renameEntry(indexPath)
}
self.fixAction(rename, text: "Rename", image: UIImage(named: "pencilEdit")!, color: UIColor(52, 61, 70))
let locate = UITableViewRowAction(style: .normal, title: stockWidth) { (_, indexPath) in
self.locateEntry(indexPath)
}
self.fixAction(locate, text: "Locate", image: UIImage(named: "locatePin")!, color: UIColor(38, 107, 215))
let delete = UITableViewRowAction(style: .normal, title: stockWidth) { (_, indexPath) in
self.deleteEntry(indexPath)
}
self.fixAction(delete, text: "Forget", image: UIImage(named: "triggerDeleteSelector")!, color: UIColor(227, 34, 60))
let gap = UITableViewRowAction(style: .normal, title: "") { (_, _) in
// pass
}
gap.backgroundColor = UIColor.clear
return [gap, delete, locate, rename]
}
There's two not obvious details there. First, the action derives its width from the text string passed in. If you didn't give it some width via some non-visible space characters, the background image wouldn't have any area to be drawn in. That's the reason for the stockWidth
string used in the first 3 actions. It's 8 character width is shared by the fixAction
method that generates the background image.
The second detail is the inclusion of the fourth "gap" action at the bottom. For some reason, if the first action has a background paint that is a tile pattern, it will stretch left under the other actions. I found that I had to insert this zero width no op action at the front to avoid that.
func fixAction(_ action:UITableViewRowAction, text:String, image:UIImage, color:UIColor) {
// make sure the image is a mask that we can color with the passed color
let mask = image.withRenderingMode(.alwaysTemplate)
// compute the anticipated width of that non empty string
let stockSize = action.title!.sizeWithAttributes([NSFontAttributeName: UIFont.systemFont(ofSize: 18)])
// I know my row height
let height:CGFloat = 70
// Standard action width computation seems to add 15px on either side of the text
let width = (stockSize.width + 30).ceiling
let actionSize = CGSize(width: width, height: height)
// lets draw an image of actionSize
UIGraphicsBeginImageContextWithOptions(actionSize, false, 0.0)
if let context = UIGraphicsGetCurrentContext() {
context.clear(CGRect(origin: .zero, size: actionSize))
}
color.set()
let attributes = [NSForegroundColorAttributeName: color, NSFontAttributeName: UIFont(name: "Avenir-Book", size: 13)]
let textSize = text.size(attributes: attributes)
// implementation of `half` extension left up to the student
let textPoint = CGPoint(x: (width - textSize.width).half, y: (height - (textSize.height * 3)).half + (textSize.height * 2))
text.draw(at: textPoint, withAttributes: attributes)
let maskHeight = textSize.height * 2
let maskRect = CGRect(x: (width - maskHeight).half, y: textPoint.y - maskHeight, width: maskHeight, height: maskHeight)
mask.draw(in: maskRect)
if let result = UIGraphicsGetImageFromCurrentImageContext() {
// adjust the passed in action's backgroundColor to a patternImage
action.backgroundColor = UIColor(patternImage: result)
}
else {
"WTH!!!".logError()
}
UIGraphicsEndImageContext()
}
UITableViewRowAction image for title
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"]];
How to add image in UITableViewRowAction?
Finally in iOS 11, SWIFT 4 We can add add image in UITableView's swipe action with help of UISwipeActionsConfiguration
@available(iOS 11.0, *)
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .normal, title: "Files", handler: { (action,view,completionHandler ) in
//do stuff
completionHandler(true)
})
action.image = UIImage(named: "apple.png")
action.backgroundColor = .red
let configuration = UISwipeActionsConfiguration(actions: [action])
return configuration
}
WWDC video at 28.34
Apple Doc
Note: I have used 50*50 points apple.png image with 50 tableview
row height
Add Image To Button In UITableView's editActionsForRowAt
One of the comments lead me to using unicode characters! Super helpful as they can be added to your normal string. Unicode characters include things like:
So all you do is pass a string with a unicode character, then a line break (\n), then your button title/text. So the basic syntax looks like:
title: "\u{1234}\n YourText "
For easy reuse (because I have multiple tables) I put the characters I wanted into a struct:
struct cellEditActionIcons {
static var editAction_Arrow = "\u{2191}"
static var editAction_Check = "\u{2713}"
static var editAction_Delete = "\u{2715}"
}
Then you can create the buttons like this:
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
var doneBut = UITableViewRowAction (style: .normal, title: "\(cellEditActionIcons.editAction_Check)\n YourText" { action, index in
//Do stuff
}
doneBut.backgroundColor = myColors.someColor
}
How to set the title for the icon at the bottom on swipe right?
Just an example. You can replace the icon and title by yours. But this is how you should do this. Use centerIconOverText
function in the library:
let mail = MGSwipeButton(title: "Mail", icon: UIImage(named: "mail.png"), backgroundColor: UIColor.blue)
mail.centerIconOverText()
Here is the output :
UIContextualAction icon and text alignment
It doesn't appear there is an answer to why the text appears, and appears mis-aligned.
For anyone who comes across this question, we ended up setting the titles to nil for these buttons to keep them "icon only".
How to show image when triggering UITableViewRowAction?
I think it's time to upgrade to these ios 11 new methods with image property
public func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
public func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
So try this
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .normal, title: "", handler: { (ac:UIContextualAction, view:UIView, success:(Bool) -> Void) in
// Call edit action
// Reset state
success(true)
})
deleteAction.image = UIImage(named: "icon_trash")
deleteAction.backgroundColor = .red
return UISwipeActionsConfiguration(actions: [deleteAction])
}
Related Topics
Invalid Signature - Code Object Is Not Signed at All
Randomly Choosing an Item from a Swift Array Without Repeating
MySQL and Swift - Upload Image and File || Would It Be Better to Use Alamofire
How to Count Rows in a Parse Class Programmatically in an iOS App Using Swift
Converting a Vision Vntextobservation to a String
How to Pretty Print Swift Dictionaries to the Console
Xcode/Simulator: How to Run Older iOS Version
What Privacy-Violating or Device-Changing Things How to Do on an Iphone
Sending Data from One Viewcontroller to Another
How to Make a Swiftui Gesture That Keeps Running Code While the View Is Pressed
Cllocationmanager Delegate Methods Are Not Getting Called(Google Maps Is Integrated)
Missing Compliance Status in Testflight
React Native Change Default iOS Simulator Device
How to Fetch User's Email Using Facebook
What Is the Meaning of This Declaration
I Want to Create Aes 128 Using Cfb Encryption with No Padding in Objective C
iOS - Return to Safari from Native App Without Opening New Tab