iosuitableviewios11uiswipeactionsconfigurationuicontextualaction

UISwipeActionsConfiguration/UIContextualAction with icon AND text AND clear background


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.


Solution

  • 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.