item 数により自動レイアウトするUICollectionViewを作ってみる



``` 
import UIKit

let kCellWidth1 = CGFloat(130)
let kCellWidth2 = CGFloat(110)
let kCellHeight = CGFloat(104)

let kMiniumSpacing = CGFloat(10)

class ViewController: UIViewController {
    var myCollectionView:UICollectionView?
    var scrWidth = CGFloat(0);
    var itemCount = 2
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        scrWidth = self.view.bounds.width
        setupCollection()
        setupTextInput()
    }

    func getRowItemCount() -> Int {
        let viewWidth = self.scrWidth
        let itemWidth = getItemSize().width
        let minPadding = getSectionInset().left
        let minItemSpacing = getMinItemSpacing()
        let rowCount = Int((viewWidth - minPadding * 2 + minItemSpacing) / (itemWidth + minItemSpacing))
        return rowCount
    }

    func getColumnItemCount() -> Int {
        let rowCount = getRowItemCount()
        guard rowCount > 0 else {
            return 0
        }
        let columnCount = Int(ceil(Double(itemCount) / Double(rowCount)))
        return columnCount
    }

    func getCollectionHeight() -> CGFloat {
        let itemHeight = getItemSize().height
        let columnCount = getColumnItemCount()
        let inset = getSectionInset()
        let lineSpacing = getMinLineSpacing()

        let height = itemHeight * CGFloat(columnCount)
                                + (inset.top + inset.bottom)
                                + lineSpacing * CGFloat(columnCount - 1)
        return height
    }
    
    func getSectionInset() -> UIEdgeInsets {
        var insets = UIEdgeInsets.zero
        let itemWidth = getItemSize().width
        let itemsWidth = CGFloat(itemCount) * itemWidth + CGFloat(itemCount - 1) * getMinItemSpacing()
        let totalWidth = itemsWidth + 2 * kMiniumSpacing
        if totalWidth < self.scrWidth {
            let newPadding = (self.scrWidth - itemsWidth) / 2.0 - 5
            insets = UIEdgeInsets(top: kMiniumSpacing, left: newPadding, bottom: kMiniumSpacing, right: newPadding)
        } else {
            insets = UIEdgeInsets(top: kMiniumSpacing, left: kMiniumSpacing, bottom: kMiniumSpacing, right: kMiniumSpacing)
        }
        return insets
    }

    func getItemSize() -> CGSize {
        let size = self.scrWidth > 375 ? CGSize(width: kCellWidth1, height: kCellHeight) :CGSize(width: kCellWidth2, height: kCellHeight)
        return size
    }

    func getMinItemSpacing() -> CGFloat {
        return 1
    }

    func getMinLineSpacing() -> CGFloat {
        return kMiniumSpacing
    }
    
    func setupCollection() {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = getSectionInset()
        layout.itemSize = getItemSize()
        layout.minimumInteritemSpacing = getMinItemSpacing()
        layout.minimumLineSpacing = getMinLineSpacing()
        layout.scrollDirection = .vertical

        let collectHeight = getCollectionHeight()
        let collectionRect =
            CGRect(origin: CGPoint(x: 0, y: 50),
                   size:CGSize(width: scrWidth, height: collectHeight))
        myCollectionView = UICollectionView(frame: collectionRect, collectionViewLayout: layout)
        myCollectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: CollectionCell.cellIdentifier)
        myCollectionView?.backgroundColor = UIColor.link

        myCollectionView?.dataSource = self
        myCollectionView?.delegate = self
        self.view.addSubview(myCollectionView ?? UICollectionView())
    }
    
    func setupTextInput() {
        let myTextField = UITextField(frame: CGRect(x: 50, y: (view.bounds.height - 80),
                                               width: 300.00, height: 30.00));
        myTextField.placeholder = "pleae enter item count"
        myTextField.backgroundColor = .link
        myTextField.keyboardType = .numbersAndPunctuation
        myTextField.delegate = self
        self.view.addSubview(myTextField)
    }
    
    func updateCollection() {
        myCollectionView?.frame.size.height = getCollectionHeight()
        if let layout = myCollectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.sectionInset = getSectionInset()
            layout.itemSize = getItemSize()
            layout.minimumInteritemSpacing = getMinItemSpacing()
            layout.minimumLineSpacing = getMinLineSpacing()
            layout.scrollDirection = .vertical
        }
        myCollectionView?.reloadData()
    }
}

```



``` 
extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return itemCount
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionCell.cellIdentifier, for: indexPath)
        myCell.backgroundColor = UIColor.blue
        return myCell
    }
}

extension ViewController: UICollectionViewDelegate {
 
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
       print("User tapped on item \(indexPath.row)")
    }
}
``` 



``` 
extension ViewController: UITextFieldDelegate {

//    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
//        guard let newValue = Int(string) else {
//            print("変換できません")
//            return true
//         }
//        itemCount = newValue
//        updateCollection()
//        return true
//    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        guard let newValue = Int(textField.text ?? "") else {
            print("変換できません")
            return false
         }
        self.view.endEditing(true)
        itemCount = newValue
        updateCollection()
        return true
    }
    
}

```