How to set UICollectionViewCell Width and Height programmatically

后端 未结 20 1032
终归单人心
终归单人心 2020-12-04 08:06

I am trying to implement a CollectionView. When I am using Autolayout, my cells won\'t change the size, but their alignment.

Now I would rather want to

相关标签:
20条回答
  • 2020-12-04 09:01

    Swift 5, Programmatic UICollectionView setting Cell width and height

    // MARK: MyViewController
    
    final class MyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
        
        private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
            let layout = UICollectionViewFlowLayout()
            let spacing: CGFloat = 1
            let numOfColumns: CGFloat = 3
            let itemSize: CGFloat = (UIScreen.main.bounds.width - (numOfColumns - spacing) - 2) / 3
            layout.itemSize = CGSize(width: itemSize, height: itemSize)
            layout.minimumInteritemSpacing = spacing
            layout.minimumLineSpacing = spacing
            layout.sectionInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing)
            return layout
        }()
        
        private lazy var collectionView: UICollectionView = {
            let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: collectionViewLayout)
            collectionView.backgroundColor = .white
            collectionView.dataSource = self
            collectionView.delegate = self
            collectionView.translatesAutoresizingMaskIntoConstraints = false
            return collectionView
        }()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            configureCollectionView()
        }
        
        private func configureCollectionView() {
            view.addSubview(collectionView)
            NSLayoutConstraint.activate([
                collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
                collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
                collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
            ])
            collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell")
        }
        
        // MARK: UICollectionViewDataSource
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return 20
        }
        
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
            cell.backgroundColor = .red
            return cell
        }
        
    }
    
    // MARK: PhotoCell
    
    final class PhotoCell: UICollectionViewCell {
        
        lazy var imageView: UIImageView = {
            let imageView = UIImageView()
            imageView.contentMode = .scaleAspectFill
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.layer.masksToBounds = true
            return imageView
        }()
        
        override init(frame: CGRect) {
            super.init(frame: frame)
            setupViews()
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init?(coder:) not implemented")
        }
        
        func setupViews() {
            addSubview(imageView)
            NSLayoutConstraint.activate([
                topAnchor.constraint(equalTo: topAnchor),
                bottomAnchor.constraint(equalTo: bottomAnchor),
                leadingAnchor.constraint(equalTo: leadingAnchor),
                trailingAnchor.constraint(equalTo: trailingAnchor)
            ])
        }
        
    }
    
    0 讨论(0)
  • 2020-12-04 09:01

    This is my version, find your suitable ratio to get the cell size as per your requirement.

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
    { 
    return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
    } 
    
    0 讨论(0)
  • 2020-12-04 09:03

    Try to use UICollectionViewDelegateFlowLayout method. In Xcode 11 or later, you need to set Estimate Size to none from storyboard.

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
    UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let padding: CGFloat =  170
        let collectionViewSize = advertCollectionView.frame.size.width - padding
        return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
    }
    
    0 讨论(0)
  • 2020-12-04 09:06

    A simple way:

    If you just need a simple fixed size:

    class SizedCollectionView: UIICollectionView {
        override func common() {
            super.common()
            let l = UICollectionViewFlowLayout()
            l.itemSize = CGSize(width: 42, height: 42)
            collectionViewLayout = l
        }
    }
    

    That's all there is to it.

    In storyboard, just change the class from UICollectionView to SizedCollectionView.

    But !!!

    Notice the base class there is "UI 'I' CollectionView". 'I' for Initializer.

    It's not that easy to add an initializer to a collection view. Here's a common approach:

    Collection view ... with initializer:

    import UIKit
    
    class UIICollectionView: UICollectionView {
        private var commoned: Bool = false
        
        override func didMoveToWindow() {
            super.didMoveToWindow()
            if window != nil && !commoned {
                commoned = true
                common()
            }
        }
        
        internal func common() {
        }
    }
    

    In most projects, you need "a collection view with an initializer". So you will probably anyway have UIICollectionView (note the extra I for Initializer!) in your project.

    0 讨论(0)
  • 2020-12-04 09:07
    **Swift 5**
    To make this work you have to do the following.
    
    Add these protocols
    
     - UICollectionViewDelegate
    
    
     - UICollectionViewDataSource
    
    
     - UICollectionViewDelegateFlowLayout
    
    Your code will then look like this
    
    extension YourViewController: UICollectionViewDelegate {
        //Write Delegate Code Here
    }
    
    extension YourViewController: UICollectionViewDataSource {
        //Write DataSource Code Here
    }
    
    extension YourViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return CGSize(width: screenWidth, height: screenWidth)
        }
    }
    
    Now the final and crucial step to see this take effect is to go to your viedDidLoad function inside your Viewcontroller.
    
        override func viewDidLoad() {
            super.viewDidLoad()
            collection.dataSource = self // Add this
            collection.delegate = self // Add this
    
            // Do any additional setup after loading the view.
        }
    
    Without telling your view which class the delegate is it won't work.
    
    0 讨论(0)
  • 2020-12-04 09:08

    The collection view has a layout object. In your case, it is probably a flow layout (UICollectionViewFlowLayout). Set the flow layout's itemSize property.

    0 讨论(0)
提交回复
热议问题