Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách sử dụng UICollectionView trong Swift

UICollectionView là control hiển thị dữ liệu theo lưới (grid), danh sách, hoặc layout tùy chỉnh mạnh mẽ hơn TableView. Cần conform UICollectionViewDataSource, UICollectionViewDelegate, và UICollectionViewDelegateFlowLayout cho size tùy chỉnh.

1. Tạo Collection View bằng code


func setupCollectionView() {
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: 100, height: 100)
    layout.minimumInteritemSpacing = 10
    layout.minimumLineSpacing = 10
    layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
    
    let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.backgroundColor = .systemGroupedBackground
    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
    collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    view.addSubview(collectionView)
}

2. DataSource (Bắt buộc)


func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 }

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 20
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    cell.backgroundColor = .systemRed
    cell.layer.cornerRadius = 8
    // Thêm label hiển thị index
    if cell.contentView.subviews.isEmpty {
        let label = UILabel(frame: cell.contentView.bounds)
        label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        label.textAlignment = .center
        label.textColor = .white
        label.font = .boldSystemFont(ofSize: 18)
        label.tag = 999
        cell.contentView.addSubview(label)
    }
    (cell.contentView.viewWithTag(999) as? UILabel)?.text = "\(indexPath.item)"
    return cell
}

3. Delegate Flow Layout (Size động)


func collectionView(_ collectionView: UICollectionView, 
                    layout collectionViewLayout: UICollectionViewLayout, 
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    // Ví dụ: 2 cột, spacing 10
    let width = (collectionView.bounds.width - 30) / 2
    return CGSize(width: width, height: width)  // Vuông
}

Kết quả

Cách sử dụng UICollectionView trong Swift

Nâng cao: Compositional Layout (iOS 13+)

Thay UICollectionViewFlowLayout bằng UICollectionViewCompositionalLayout cho layout phức tạp (nested groups, orthogonal scrolling, header/footer, badge...).


func createLayout() -> UICollectionViewLayout {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1.0))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    item.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
    
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.5))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .continuous  // Hoặc .groupPaging, .none
    
    return UICollectionViewCompositionalLayout(section: section)
}

// Sử dụng:
let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())

Lưu ý

  • Luôn dùng dequeueReusableCell(withReuseIdentifier:for:) – không init cell mới mỗi lần.
  • Custom Cell: Tạo class kế thừa UICollectionViewCell, register nib/class.
  • Supplementary Views (Header/Footer): register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "header").
  • Diffable Data Source (iOS 13+): UICollectionViewDiffableDataSource – cập nhật data an toàn, animate tự động.