5 votes

L'auto-dimensionnement dans la sous-classe personnalisée de UICollectionViewListCell ne fonctionne pas dans iOS 14

Le contexte :

iOS14 a introduit une nouvelle façon d'enregistrer et de configurer collectionViewCell et In Listes dans CollectionView Vidéo de la WWDC : un développeur d'Apple affirme que l'autodimensionnement est une valeur par défaut. UICollectionViewListCell et nous n'avons pas besoin de spécifier explicitement la hauteur des cellules. Cela fonctionne très bien si j'utilise la cellule de liste du système dans diverses configurations, mais l'auto-dimensionnement échoue lorsque je l'utilise avec une sous-classe personnalisée de UICollectionViewListCell

Qu'est-ce que j'ai essayé ?

iOS 14 a introduit une nouvelle façon de configurer les cellules, où nous n'accédons pas directement aux composants des cellules pour définir les diverses propriétés de l'interface utilisateur, mais où nous utilisons les éléments suivants content configuration y background configuration pour mettre à jour/configurer les cellules. Cela devient un peu délicat lorsque nous utilisons des cellules personnalisées.

CustomSkillListCollectionViewCell

class CustomSkillListCollectionViewCell: UICollectionViewListCell {
    var skillLavel: String? {
        didSet {
            setNeedsUpdateConfiguration()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func updateConfiguration(using state: UICellConfigurationState) {
        backgroundConfiguration = SkillListViewBackgroundConfiguration.getBackgroundConfiguration(for: state)
        var content = SkillListViewContentConfiguration().updated(for: state)
        content.label = skillLavel
        contentConfiguration = content
    }
}

SkillListViewBackgroundConfiguration

struct SkillListViewBackgroundConfiguration {
    @available(iOS 14.0, *)
    static func getBackgroundConfiguration(for state: UICellConfigurationState) -> UIBackgroundConfiguration {
        var background = UIBackgroundConfiguration.clear()
        if state.isHighlighted || state.isSelected {
            background.backgroundColor = UIColor.green.withAlphaComponent(0.4)
        }
        else if state.isExpanded {
            background.backgroundColor = UIColor.red.withAlphaComponent(0.5)
        }
        else {
            background.backgroundColor = UIColor.red.withAlphaComponent(0.9)
        }
        return background
    }
}

SkillListViewContentConfiguration

struct SkillListViewContentConfiguration: UIContentConfiguration {
    var label: String? = nil

    @available(iOS 14.0, *)
    func makeContentView() -> UIView & UIContentView {
        return SkillListView(contentConfiguration: self)
    }

    @available(iOS 14.0, *)
    func updated(for state: UIConfigurationState) -> Self {
        guard let state = state as? UICellConfigurationState else {
            return self
        }
        let updatedConfig = self
        return updatedConfig
    }
}

Enfin, la vue secondaire SkillListView

class SkillListView: UIView, UIContentView {
    var configuration: UIContentConfiguration {
        get {
            return self.appliedConfiguration
        }
        set {
            guard let newConfig = newValue as? SkillListViewContentConfiguration else { return }
            self.appliedConfiguration = newConfig
            apply()
        }
    }

    private var appliedConfiguration: SkillListViewContentConfiguration!
    var skillNameLabel: UILabel!

    @available(iOS 14.0, *)
    init(contentConfiguration: UIContentConfiguration) {
        super.init(frame: .zero)
        self.setUpUI()
        self.configuration = contentConfiguration
        self.apply()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func apply() {
        self.skillNameLabel.text = self.appliedConfiguration.label
    }

    private func setUpUI() {
        self.skillNameLabel = UILabel(frame: .zero)
        skillNameLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
        skillNameLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
        self.skillNameLabel.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(skillNameLabel)
        NSLayoutConstraint.activate([
            self.skillNameLabel.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: 20),
            self.skillNameLabel.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: 20),
            self.skillNameLabel.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: 20)
        ])
    }
}

Et je le configure en utilisant

    let skillsCellConfigurator = UICollectionView.CellRegistration<CustomSkillListCollectionViewCell, Employee> { (cell, indexPath, employee) in
        cell.skillLavel = employee.individualSkil
        cell.accessories = [.disclosureIndicator()]
    }

Question :

Tout le reste fonctionne parfaitement, sauf la hauteur

enter image description here

0voto

user3338275 Points 90

Tout d'abord, vous avez besoin d'au moins une contrainte supplémentaire pour garantir la satisfaction, car le haut, le bas et l'avant ont besoin d'un arrière ou d'un centreX pour les accompagner. Mais surtout, il s'agit probablement d'une contrainte sur les marges plutôt que sur la vue supérieure. Les cellules devraient automatiquement respecter les marges comme la zone de sécurité tant que le UICollectionView lui-même les respecte, ce qui, je pense, est le comportement par défaut. Le layoutmarginguide pour les cellules est significativement poussé vers le bas en haut, ce qui peut être vu à partir d'un exemple fictif dans interfacebuilder si vous vérifiez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X