5

There are a couple of similar questions out there (e.g. my previous iOS10 variant), but I think there should be up an up to date answer for iOS 11, using Swift4, that doesn't use private APIs, and doesn't rely on you restricting your icon to the unicode emoji.

With the evolution in APIs to iOS11, we can now put image and text, but they are forced into template mode and reverse colored with whatever backgroundColor you set. E.g.

let rename = UIContextualAction(style: .normal, title: "Rename") { (_, view, _) in
    self.renameEntry(indexPath)
}
rename.backgroundColor = UIColor.black
rename.image = UIImage(named: "pencilEdit")
let locate = UIContextualAction(style: .normal, title: "Locate") { (_, view, _) in
    self.locateEntry(indexPath)
}
locate.backgroundColor = UIColor.blue
locate.image = UIImage(named: "locatePin")
let delete = UIContextualAction(style: .destructive, title: "Forget") { (_, view, _) in
    self.deleteEntry(indexPath)
}
delete.backgroundColor = UIColor.red
delete.image = UIImage(named: "triggerDeleteSelector")
return UISwipeActionsConfiguration(actions: [rename, locate, delete])

which produces this:

enter image description here

So apparently, we can have image OR text, but not both.

But the look I want is

enter image description here

Aside from the backwards order, I'm at a loss how to trick the system like I was able to for iOS10. I can still generate an image with both text AND image, but I cannot control the color of that image. Setting backgroundColor to nil or .clear just makes empty squares.

Travis Griggs
  • 21,522
  • 19
  • 91
  • 167

1 Answers1

4

Use patternImage to set the background color and don't set the title or image. This is a hacky trick but it should work for your situation.

let rename = UIContextualAction(style: .normal, title: nil) { (_, view, _) in 
        self.renameEntry(indexPath) 
}
rename.backgroundColor = UIColor(patternImage: UIImage(named: "pencilEditWideFrame")!)

You have to save your images with wide frames like this with the icon at the far left so they don't actually repeat:

enter image description here

Note: I tested this and it works when using two or more contextual actions but doesn't work with just one. The pattern ends up repeating on a full swipe.

This also assumes that you have a plain background behind your tableview that you can use for the background color of the image as transparency is still a no-go.

Matt Rundle
  • 1,609
  • 1
  • 9
  • 11
  • It's interesting, if you use the old `UITableViewRowAction` and my previous post, you will get a runtime console warning that using a patternImage as the background color is deprecated. But no such warning for the new class. – Travis Griggs Nov 20 '17 at 22:42
  • 2
    I have a different size in my cells? And the background - a lot of images, and not the one in the center? How can I fix it? – WorieN Mar 22 '18 at 17:14
  • This hack is so precious! Thanks for that Matt! – MarcinR Sep 05 '18 at 10:54
  • How did the title come below the image? Nothing set in the code – Satyam Aug 09 '19 at 15:18
  • Title is part of the image. This is a hack after all ;) – Matt Rundle Aug 09 '19 at 21:28