Tuesday, March 5, 2024
HomeiOS Developmentios - Utilizing `UIButton.Configuration` in a `UICollectionViewCell` breaks the label placement when...

ios – Utilizing `UIButton.Configuration` in a `UICollectionViewCell` breaks the label placement when rotating


When utilizing a UIButton, with a UIButton.Configuration to set its title and picture, inside a UICollectionViewCell the button itself breaks the picture/label positioning when rotating.

That is what it appears like initially:

initial

Then after rotating as soon as

rotated once

After which when rotating again

rotating back

Code:

import UIKit

ultimate class ViewController: UIViewController {
    non-public let cellRegistration = UICollectionView.CellRegistration<ButtonCollectionViewCell, String> { _, _, _ in }

    non-public lazy var dataSource = UICollectionViewDiffableDataSource<String, String>(
        collectionView: collectionView,
        cellProvider: { collectionView, indexPath, identifier in
            collectionView.dequeueConfiguredReusableCell(
                utilizing: self.cellRegistration,
                for: indexPath,
                merchandise: ""
            )
        }
    )

    non-public lazy var collectionView: UICollectionView = {
        let collectionViewLayout = UICollectionViewCompositionalLayout { _, _ in
            let layoutSize = NSCollectionLayoutSize(
                widthDimension: .fractionalWidth(1.0),
                heightDimension: .estimated(30)
            )

            let group = NSCollectionLayoutGroup.horizontal(
                layoutSize: layoutSize,
                subitems: [
                    NSCollectionLayoutItem(layoutSize: layoutSize)
                ]
            )

            let format = NSCollectionLayoutSection(group: group)
            format.contentInsetsReference = .safeArea
            format.contentInsets = NSDirectionalEdgeInsets(high: 24, main: 12, backside: 0, trailing: 12)
            return format
        }

        return UICollectionView(body: .zero, collectionViewLayout: collectionViewLayout)
    }()

    override func viewDidLoad() {
        tremendous.viewDidLoad()

        var snapshot = NSDiffableDataSourceSnapshot<String, String>()
        snapshot.appendSections(["section"])
        snapshot.appendItems(["item"], toSection: "part")
        
        dataSource.apply(snapshot)

        view.addSubview(collectionView)
    }

    override func viewDidLayoutSubviews() {
        tremendous.viewDidLayoutSubviews()

        collectionView.body = view.bounds
    }
}

ultimate class ButtonView: UIView {
    non-public lazy var button: UIButton = {
        let picture = UIImage(systemName: "headphones")!
            .withTintColor(.white)
            .withRenderingMode(.alwaysOriginal)

        let title = AttributedString(NSAttributedString(string: "Hear", attributes: [
            .foregroundColor: UIColor.white
        ]))

        var configuration = UIButton.Configuration.plain()
        configuration.attributedTitle = title
        configuration.picture = picture
        configuration.titleAlignment = .heart
        configuration.imagePadding = 4
        configuration.background.backgroundColor = .blue
        configuration.background.cornerRadius = 8

        return UIButton(configuration: configuration)
    }()

    override init(body: CGRect) {
        tremendous.init(body: body)
        addSubview(button)
    }

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

    override func layoutSubviews() {
        tremendous.layoutSubviews()
        button.body = bounds
    }

    override func sizeThatFits(_ measurement: CGSize) -> CGSize {
        button.sizeThatFits(measurement)
    }
}

ultimate class ButtonCollectionViewCell: UICollectionViewCell {
    non-public let buttonView = ButtonView()

    override init(body: CGRect) {
        tremendous.init(body: body)
        contentView.addSubview(buttonView)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been applied")
    }

    override func layoutSubviews() {
        tremendous.layoutSubviews()
        buttonView.body = contentView.bounds
    }

    override func sizeThatFits(_ measurement: CGSize) -> CGSize {
        buttonView.sizeThatFits(measurement)
    }
}

The view inspector does not yield something helpful both

view inspector

The one factor I’ve discovered that helps is setting the autoresizingMask of the UIButton and its container view, which a) make no sense in any respect b) does not work exterior this pattern app to breed it (e.g. the answer is just not fully dependable)

Additionally utilizing the “previous” APIs, setTitle("Title", for: .regular) / setImage(picture, for: .regular) doesn’t trigger this bug.

Anybody seen this earlier than and have any clue what might potential be incorrect right here?



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments