Basic use of UIListContentConfiguration and UIBackgroundConfiguration in UITableViewCell?

Viewed 2243

I'm trying to experiment with replacing my UITableViewCell configuration with the new iOS 14 UIListContentConfiguration and UIBackgroundConfiguration, but I don't see how to perform even the most elementary customizations.

For example, I've got a test cell where, in my data source cellForRowAt:, I was configuring the background like this:

let v = UIImageView(image: UIImage(named:"linen.png"))
v.contentMode = .scaleToFill
cell.backgroundView = v

let v2 = UIView()
v2.backgroundColor = UIColor.blue.withAlphaComponent(0.2)
cell.selectedBackgroundView = v2

The idea is that we have an image as the background of the cell, and when the user taps on the cell to select it, we overlay that with a transparent blue tint. The selectedBackgroundView sits in front of the backgroundView when the cell is selected.

Okay, so how do I do that with UIBackgroundConfiguration? I see how to configure the background view:

var back = UIBackgroundConfiguration.listPlainCell()
let v = UIImageView(image: UIImage(named:"linen.png"))
v.contentMode = .scaleToFill
back.customView = v
cell.backgroundConfiguration = back

But what about what happens when there's a selection? There's no selectedCustomView, and I don't see any provision here for different backgrounds for different states.

1 Answers

The following seems to be what you're expected to do. In cellForRowAt:, instead of configuring the background view, tell the cell not to update its background automatically:

cell.automaticallyUpdatesBackgroundConfiguration = false

What that means is: I've got a custom cell subclass, it overrides updateConfiguration(using:), and I want you to call that override whenever you need the background configuration.

Okay, so now do that. In your cell subclass, override updateConfiguration(using:). In that override, do whatever you would have done in cellForRowAt:, but now you can take account of the current state. There is no selectedCustomView, so just do or don't overlay the selection tint on top of the customView itself:

class MyCell : UITableViewCell {
    override func updateConfiguration(using state: UICellConfigurationState) {
        var back = UIBackgroundConfiguration.listPlainCell().updated(for: state)
        let v = UIImageView(image: UIImage(named:"linen.png"))
        v.contentMode = .scaleToFill
        if state.isSelected || state.isHighlighted {
            let v2 = UIView()
            v2.backgroundColor = UIColor.blue.withAlphaComponent(0.2)
            v.addSubview(v2)
            v2.frame = v.bounds
            v2.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        }
        back.customView = v
        self.backgroundConfiguration = back
    }
}

That works as expected. When the cell is selected, it has the blue tint; when it isn't, it doesn't.

At first blush, it may seem nutty to have to create a cell subclass just for this. But that is, in fact, the whole point. The entire philosophy of this new configuration-based architecture is that it was never the business of the data source (cellForRowAt) to configure the cell's view features in detail. The configuration should be lightweight from the point of view of the data source. Let the cell worry about what the configuration means in terms of its subviews.

Related