Thursday, April 30, 2026
HomeiOS DevelopmentUICollectionView cells with round photos plus rotation assist

UICollectionView cells with round photos plus rotation assist

[ad_1]

Round cells inside a group view

Reaching the purpose is comparatively simple, but when you do not know what is going on on within the background it is may gona be more durable than you’ll suppose first. So let’s create a brand new undertaking add a storyboard with a UICollectionViewController, drag a UIImageView contained in the cell, resize it, add some constraints, set the cell identifier.



It ought to look one thing just like the picture above. Nothing particular only a easy UI for our instance software. Now seek for some random picture, add it to the undertaking and let’s do some actual coding. First I will present you the little trick within the cell subclass.


class Cell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!

    override var bounds: CGRect {
        didSet {
            self.layoutIfNeeded()
        }
    }

    override func awakeFromNib() {
        tremendous.awakeFromNib()

        self.imageView.layer.masksToBounds = true
    }

    override func layoutSubviews() {
        tremendous.layoutSubviews()

        self.setCircularImageView()
    }

    func setCircularImageView() {
        self.imageView.layer.cornerRadius = CGFloat(roundf(Float(self.imageView.body.dimension.width / 2.0)))
    }
}


Are you able to see it? Sure, it is best to override the bounds property. As the following step now we have to jot down the controller class with some fundamental knowledge supply for the gathering view and with the correct assist for the rotation strategies. 🤓


class ViewController: UICollectionViewController {

    override func collectionView(_ collectionView: UICollectionView,
                                 numberOfItemsInSection part: Int) -> Int {
        return 30
    }

    override func collectionView(_ collectionView: UICollectionView,
                                 cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell

        cell.imageView.picture = UIImage(named: "Instance.jpg")
        cell.imageView.backgroundColor = .lightGray

        return cell
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        tremendous.traitCollectionDidChange(previousTraitCollection)

        guard
            let previousTraitCollection = previousTraitCollection,
            self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass ||
            self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass
        else {
            return
        }

        self.collectionView?.collectionViewLayout.invalidateLayout()
        self.collectionView?.reloadData()
    }

    override func viewWillTransition(to dimension: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        tremendous.viewWillTransition(to: dimension, with: coordinator)

        self.collectionView?.collectionViewLayout.invalidateLayout()

        coordinator.animate(alongsideTransition: { context in

        }, completion: { context in
            self.collectionView?.collectionViewLayout.invalidateLayout()

            self.collectionView?.visibleCells.forEach { cell in
                guard let cell = cell as? Cell else {
                    return
                }
                cell.setCircularImageView()
            }
        })
    }
}

extension ViewController: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView,
                        structure collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {

        return CGSize(width: collectionView.body.dimension.width/3.0 - 8,
                      top: collectionView.body.dimension.width/3.0 - 8)
    }
}


In case you are aware of assortment views, you may ask why am I doing this tutorial? It is so easy. It simply works, proper? No, really with out the overridden bounds property the instance would look one thing like this on the left aspect. 😢


Humorous, huh? The picture on the fitting aspect is the precise consequence with the overridden bounds, that is the anticipated behaviour. Scrolling and rotation goes to be actually unusual should you do not override bounds and you do not reset the cornerRadius property for the seen views. You may ask: however why? 🤔

Layers, springs & struts and a few clarification

Apple nonetheless has “Springs & Struts” based mostly code within UIKit. Which means body and certain calculations are occurring within the underlying system and the constraint system is attempting to work arduous as nicely to determine the correct measures.

“Springs & Struts” must die!

Whereas there’s an init(body:) technique, or a required init(coder:) these structure issues will suck as hell. I actually like Interface Builder, however till we cannot get a high-quality software to create nice consumer interfaces IB goes to be simply one other layer of doable bugs.

This concern will not even be there should you create the cell from code solely utilizing autolayout constraints or structure anchors! It is as a result of IB creates the cell based mostly on the body you gave in when you designed your prototype. However should you overlook init(body:) and also you simply create a brand new UIImageView occasion and let auto structure do the arduous work, the structure system will resolve every part else. Verify this.


class Cell: UICollectionViewCell {

    weak var imageView: UIImageView!

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

    override init(body: CGRect) {
        tremendous.init(body: body)

        self.translatesAutoresizingMaskIntoConstraints = false

        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(imageView)
        self.imageView = imageView

        self.imageView.topAnchor.constraint(equalTo: self.topAnchor)
        self.imageView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
        self.imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor)
        self.imageView.trailingAnchor.constraint(equalTo: self.trailingAnchor)
    }

    override func layoutSubviews() {
        tremendous.layoutSubviews()

        self.imageView.layer.masksToBounds = true
        self.imageView.layer.cornerRadius = CGFloat(roundf(Float(self.imageView.body.dimension.width/2.0)))
    }
}


Clearly it’s a must to write extra code, register your cell class manually contained in the controller class and also you additionally need to override the layoutSubviews technique contained in the cell, however it’ll work as it’s anticipated. 🙄

self.collectionView?.register(Cell.self, forCellWithReuseIdentifier: "Cell")


Anyway, after you register the programmatically created cell you may have a pleasant approach of displaying round photos. Utilizing this system is sort of tough, however it undoubtedly works in each case. You possibly can obtain the instance from The.Swift.Dev. tutorials on github.

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments