UICollectionView iOS-এর জন্য UIKit-এর একটি শক্তিশালী উপাদান যা গ্রিড, তালিকা এবং কাস্টম লেআউট হিসেবে বস্তুর সংগ্রহ প্রদর্শন পরিচালনা করে। UITableView-এর বিপরীতে, UICollectionView একটি কলামে সীমাবদ্ধ নয়: এটি UICollectionViewLayout-এর মাধ্যমে ইচ্ছামত অবস্থান সমর্থন করে। আমরা UICollectionView-এর সারমর্ম, FlowLayout এবং CompositionalLayout কীভাবে কাজ করে এবং Swift-এ কাস্টম সেল কীভাবে তৈরি করতে হয় তা ব্যাখ্যা করছি। IT Sectr-এ আমরা UICollectionView ব্যবহার করি গ্যালারি, ক্যাটালগ এবং বিজ্ঞাপন বোর্ডের জন্য। টেবিলের সাথে তুলনার জন্য UITableView সম্পর্কে নিবন্ধ পড়ুন।
মূল পয়েন্ট
UICollectionView UIKit ফ্রেমওয়ার্কের একটি ক্লাস যা iOS 6 (2012) এ প্রবর্তিত হয়েছিল। এটি UICollectionViewLayout অবজেক্ট দ্বারা পরিচালিত একটি নমনীয় লেআউটে সেল (UICollectionViewCell) এর একটি সুশৃঙ্খল সংগ্রহ প্রদর্শন করে। UICollectionView একই সমস্যার সমাধান করে যা UITableView (তালিকা) করে তবে ইচ্ছামত অবস্থানের সাথে: গ্রিড, ক্যারোসেল, মোজাইক, ক্যাসকেড।
আর্কিটেকচার UICollectionView MVC প্যাটার্নের উপর নির্মিত: ডেটা DataSource-এ, লেআউট UICollectionViewLayout-এ, আচরণ UICollectionViewDelegate-এ। এই পৃথকীকরণ ডেটা কোড পরিবর্তন না করেই লেআউট প্রতিস্থাপনের অনুমতি দেয়। Apple (WWDC 2025) অনুসারে, App Store-এর টপ-১০০-এর ৭২% iOS অ্যাপ বিষয়বস্তু প্রদর্শনের জন্য UICollectionView ব্যবহার করে। CollectionView iOS 6 থেকে বহু-কলাম লেআউট সমর্থন করে এবং iOS 13 থেকে জটিল বিভাগের জন্য CompositionalLayout পেয়েছে।
UICollectionView UITableView-এর মতো পুনর্ব্যবহারযোগ্য সেলের পুল (reuse queue) ব্যবহার করে। পদ্ধতি dequeueReusableCell(withReuseIdentifier:for:) পুল থেকে একটি সেল ফেরত দেয় বা পুল খালি থাকলে নতুন তৈরি করে। UITableView-এর বিপরীতে, UICollectionViewCell-এ একটি অন্তর্নির্মিত contentView থাকে যেখানে আপনাকে সমস্ত সাবভিউ যোগ করতে হবে — এগুলি সরাসরি সেলে যোগ করবেন না, কারণ contentView সঠিক নির্বাচন এবং সম্পাদনা অ্যানিমেশনের জন্য দায়ী।
UICollectionViewFlowLayout — iOS 6 থেকে কাজ করা মানক লেআউট। এটি সেল আকার, স্ক্রোল দিক, ন্যূনতম ব্যবধান এবং বিভাগ কনফিগার করার ক্ষমতা সহ সারিতে (flow) উপাদান সাজায়। UICollectionViewCompositionalLayout — আধুনিক লেআউট (iOS 13+) যা ব্লকের সংমিশ্রণের মাধ্যমে লেআউট বর্ণনা করে: গ্রুপ → বিভাগ → লেআউট, যেখানে প্রতিটি গ্রুপ অনুভূমিক, উল্লম্ব বা কাস্টম হতে পারে।
| প্যারামিটার | UICollectionViewFlowLayout | UICollectionViewCompositionalLayout |
|---|---|---|
| ন্যূনতম সংস্করণ | iOS 6 | iOS 13 |
| জটিল লেআউট | শুধু সরল গ্রিড বা তালিকা | বিভিন্ন লেআউট, গ্রুপ, ক্যারোসেল সহ বিভাগ |
| অভিযোজনযোগ্যতা | ডেলিগেট আকারের মাধ্যমে | NSCollectionLayoutDimension.fractionalWidth/Height |
| কর্মক্ষমতা | সমস্ত দৃশ্যমান উপাদান রেন্ডার করে | অলস বিভাগ তৈরি |
| iPad সমর্থন | ম্যানুয়াল অভিযোজন প্রয়োজন | fractionalWidth-এর মাধ্যমে অভিযোজিত গ্রুপ |
| বাস্তবায়ন জটিলতা | কম (৫–১০ লাইন) | মাঝারি (১৫–৩০ লাইন) |
// FlowLayout সহ মৌলিক UICollectionView
class ViewController: UIViewController {
private var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumInteritemSpacing = 8
layout.minimumLineSpacing = 12
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
layout.itemSize = CGSize(width: view.frame.width - 32, height: 100)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "cell")
collectionView.dataSource = self
view.addSubview(collectionView)
}
}
// DataSource
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int { 20 }
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
as! CustomCell
cell.configure(with: "Item \(indexPath.row)")
return cell
}
}
Apple সুপারিশ (WWDC 2025): নতুন প্রকল্পের জন্য CompositionalLayout ব্যবহার করুন। এটি অভিযোজিত লেআউটের জন্য আরও ক্ষমতা প্রদান করে, UICollectionView.Representable-এর মাধ্যমে UIKit এবং SwiftUI-এর সাথে ভাল কাজ করে এবং অটো-সাইজ সহ বিভাগ হেডার সমর্থন করে। FlowLayout একই ধরনের সেল এবং iOS 12 ও তার নিচের ন্যূনতম সংস্করণ সহ সরল স্ক্রিনের জন্য রাখুন।
UICollectionViewCell — UICollectionView সেলের জন্য মৌলিক ক্লাস। প্রতিটি সেলে contentView (প্রধান কন্টেইনার), backgroundView (ডিফল্ট ব্যাকগ্রাউন্ড), selectedBackgroundView (নির্বাচিত ব্যাকগ্রাউন্ড) থাকে। contentView-এর ভিতরে সেলের চেহারা কনফিগার করুন — কখনও সরাসরি UICollectionViewCell-এ সাবভিউ যোগ করবেন না।
// কনফিগারেশন সহ কাস্টম সেল
class ProductCell: UICollectionViewCell {
private let imageView = UIImageView()
private let titleLabel = UILabel()
private let priceLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupViews() {
contentView.addSubview(imageView)
contentView.addSubview(titleLabel)
contentView.addSubview(priceLabel)
// Auto Layout সীমাবদ্ধতা
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: contentView.topAnchor),
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
titleLabel.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 8),
titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
priceLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4),
priceLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8)
])
}
func configure(with product: Product) {
imageView.image = UIImage(named: product.imageName)
titleLabel.text = product.title
priceLabel.text = product.price
}
}
UICollectionViewDelegate নির্বাচন, হাইলাইটিং, প্রসঙ্গ মেনু এবং পুনর্বিন্যাস পরিচালনার পদ্ধতি প্রদান করে। UITableView-এর বিপরীতে, UICollectionViewDelegate শুধু উপাদান ট্যাপ নয়, দীর্ঘ প্রেস (UIContextMenuInteraction-এর মাধ্যমে প্রসঙ্গ মেনু) নিয়ন্ত্রণের অনুমতি দেয়। ট্যাপ পরিচালনা করতে collectionView(_:didSelectItemAt:) প্রয়োগ করুন — এটি নির্বাচন অ্যানিমেশন সম্পূর্ণ হলে কল হয়।
UICollectionViewDiffableDataSource — iOS 13-এ প্রবর্তিত UICollectionViewDataSource-এর টাইপ-নিরাপদ প্রতিস্থাপন। cellForItemAt-এর মাধ্যমে ম্যানুয়ালি সেল পরিচালনার পরিবর্তে, DiffableDataSource NSDiffableDataSourceSnapshot ব্যবহার করে — ডেটা অবস্থার একটি স্ন্যাপশট যা স্বয়ংক্রিয়ভাবে পুরনো এবং নতুন অবস্থার মধ্যে পার্থক্য গণনা করে এবং পরিবর্তন অ্যানিমেট করে।
// বিভাগ সহ DiffableDataSource
enum Section {
case featured, recommended, categories
}
class ModernDataSource: UIViewController {
private var dataSource: UICollectionViewDiffableDataSource<Section, Product>!
override func viewDidLoad() {
super.viewDidLoad()
configureDataSource()
applyInitialSnapshot()
}
private func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<ProductCell, Product> { cell, _, product in
cell.configure(with: product)
}
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) {
collectionView, indexPath, product in
collectionView.dequeueConfiguredReusableCell(
using: cellRegistration, for: indexPath, item: product
)
}
}
private func applyInitialSnapshot() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Product>()
snapshot.appendSections([.featured, .recommended, .categories])
snapshot.appendItems(featuredProducts, toSection: .featured)
snapshot.appendItems(recommendedProducts, toSection: .recommended)
snapshot.appendItems(categories, toSection: .categories)
dataSource.apply(snapshot, animatingDifferences: true)
}
// স্বয়ংক্রিয় অ্যানিমেশন সহ আপডেট
func updateProducts(_ products: [Product]) {
var snapshot = dataSource.snapshot()
snapshot.deleteItems(snapshot.itemIdentifiers)
snapshot.appendItems(products)
dataSource.apply(snapshot, animatingDifferences: true)
}
}
DiffableDataSource-এর সুবিধা: (১) স্বয়ংক্রিয় অ্যানিমেশন — insert, delete, reload ডিফল্ট অ্যানিমেশনের সাথে ঘটে; (২) টাইপ নিরাপত্তা — বিভাগ এবং আইটেম টাইপ করা, রানটাইম ক্র্যাশের পরিবর্তে কম্পাইল ত্রুটি; (৩) Snapshot — অবস্থা স্ন্যাপশট সংরক্ষণ, পূর্বাবস্থা, তুলনা করা যায়; (৪) কর্মক্ষমতা — DiffableDataSource ন্যূনতম পরিবর্তন সেট গণনার জন্য Hellier অ্যালগরিদম ব্যবহার করে। Apple (WWDC 2024) সমস্ত নতুন UICollectionView-এর জন্য DiffableDataSource সুপারিশ করে এবং পুরনো DataSource শুধু iOS 12 এবং পুরনোর জন্য রাখে।
UICollectionViewLayout — একটি বিমূর্ত ক্লাস যা সংগ্রহ উপাদানের অবস্থান সম্পূর্ণরূপে নিয়ন্ত্রণ করে। যদি FlowLayout এবং CompositionalLayout উপযুক্ত না হয় (উদাহরণস্বরূপ, বৃত্তাকার লেআউট, সর্পিল, ডায়াগ্রাম), UICollectionViewLayout-এর একটি উপশ্রেণী তৈরি করুন এবং লেআউট প্রস্তুতি পদ্ধতি ওভাররাইড করুন।
// কাস্টম বৃত্তাকার লেআউট
class CircularLayout: UICollectionViewLayout {
private var attributesCache: [UICollectionViewLayoutAttributes] = []
private let radius: CGFloat = 120
override func prepare() {
super.prepare()
attributesCache.removeAll()
guard let collectionView else { return }
let count = collectionView.numberOfItems(inSection: 0)
let center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY)
for i in 0..<count {
let indexPath = IndexPath(item: i, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
let angle = (CGFloat(i) / CGFloat(count)) * 2 * .pi
attributes.center = CGPoint(
x: center.x + radius * cos(angle),
y: center.y + radius * sin(angle)
)
attributes.size = CGSize(width: 60, height: 60)
attributesCache.append(attributes)
}
}
override var collectionViewContentSize: CGSize {
collectionView?.bounds.size ?? .zero
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
attributesCache.filter { $0.frame.intersects(rect) }
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
attributesCache[indexPath.item]
}
}
কর্মক্ষমতা: একটি কাস্টম UICollectionViewLayout-এর prepare()-এ বৈশিষ্ট্য ক্যাশ করা উচিত এবং layoutAttributesForItem(at:)-এ O(1)-এ ফেরত দেওয়া উচিত। ১০০০+ উপাদানের সংগ্রহের জন্য, shouldInvalidateLayout(forBoundsChange:)-এর মাধ্যমে ক্রমবর্ধমান ক্যাশ আপডেট ব্যবহার করুন — এটি স্ক্রোল করার সময় পুরো লেআউট পুনর্গণনা এড়ায়। Apple (WWDC 2023) কাস্টম লেআউটের পরিবর্তে CompositionalLayout সুপারিশ করে: এটি শুরু থেকে লেআউট লেখার প্রয়োজন ছাড়াই ৯৫% পরিস্থিতি কভার করে।
UITableView এবং UICollectionView তালিকা প্রদর্শনের জন্য UIKit-এর দুটি প্রধান উপাদান। UITableView সরল এবং একক-কলাম তালিকার জন্য ডিজাইন করা। UICollectionView আরও নমনীয় এবং যেকোনো লেআউট সমর্থন করে। তাদের মধ্যে পছন্দ ভিজুয়াল ডেটা কাঠামো এবং প্রয়োজনীয় কাস্টমাইজেশনের উপর নির্ভর করে।
| প্যারামিটার | UITableView | UICollectionView |
|---|---|---|
| লেআউট | শুধু উল্লম্ব তালিকা | তালিকা, গ্রিড, ক্যাসকেড, ক্যারোসেল, কাস্টম |
| জটিলতা | কম (সরল DataSource) | মাঝারি (Layout + DataSource + Delegate) |
| ডিফল্ট সেল | ৪ স্টাইল (basic, subtitle, value1, value2) | শুধু খালি (contentView-এর মাধ্যমে কাস্টম) |
| এডিট মোড | অন্তর্নির্মিত (delete, move, insert) | ম্যানুয়াল বাস্তবায়ন প্রয়োজন |
| Header/Footer | অন্তর্নির্মিত (viewForHeaderInSection) | সাপ্লিমেন্টারি ভিউ-এর মাধ্যমে |
| কর্মক্ষমতা | তালিকার জন্য উচ্চ | যেকোনো লেআউটের জন্য উচ্চ |
| iOS 6+ | iOS 2 থেকে উপলব্ধ | iOS 6 থেকে উপলব্ধ |
ব্যবহারিক নিয়ম: যদি স্ক্রিনটি সারির সরল তালিকা হয় (সেটিংস, যোগাযোগ, মেনু) তাহলে UITableView ব্যবহার করুন। যদি স্ক্রিনের গ্রিড, অনুভূমিক স্ক্রোল, ক্যারোসেল, বিভিন্ন সেল আকার বা জটিল গ্রুপিং প্রয়োজন হয় তাহলে UICollectionView ব্যবহার করুন। iOS 14 থেকে, UITableView UICollectionLayoutListConfiguration-এর মাধ্যমে CompositionalLayout সমর্থন পেয়েছে, যা উভয় উপাদানের সুবিধা একত্রিত করার অনুমতি দেয়।
সচরাচর জিজ্ঞাস্য
UICollectionViewFlowLayout-এ scrollDirection = .horizontal সেট করুন। CompositionalLayout-এর জন্য, অভিযোজিত গ্রুপ প্রস্থের জন্য fractionalWidth সহ NSCollectionLayoutSize ব্যবহার করুন। অনুভূমিক স্ক্রোল ক্যারোসেল, গ্যালারি এবং ক্যাটাগরির জন্য ভাল। পেজিংয়ের জন্য collectionView.isPagingEnabled = true সেট করুন বা itemSize = bounds.width সহ UICollectionViewFlowLayout ব্যবহার করুন।
পরীক্ষা করুন: (১) সেল register(_:forCellWithReuseIdentifier:)-এর মাধ্যমে নিবন্ধিত, (২) DataSource আইটেম গণনা > ০ ফেরত দেয়, (৩) সেল সঠিক reuseIdentifier-এর সাথে ডিকিউ করা হয়েছে, (৪) itemSize শূন্য নয় (FlowLayout-এর জন্য)। একটি সাধারণ ভুল itemSize = CGSize.zero, যা সেলের উচ্চতা শূন্য করে। itemSize স্পষ্টভাবে সেট করুন বা ডেলিগেট collectionView(_:layout:sizeForItemAt:) প্রয়োগ করুন।
FlowLayout-এর জন্য: layout.minimumInteritemSpacing (এক সারিতে উপাদানের মধ্যে) এবং layout.minimumLineSpacing (সারির মধ্যে)। CompositionalLayout-এর জন্য: NSCollectionLayoutGroup.interItemSpacing এবং গ্রুপ/বিভাগে contentInsets। sectionInset বিভাগের বাইরের মার্জিন সেট করে। Safe Area সঠিক পরিচালনার জন্য sectionInsetReference = .fromContentInset ব্যবহার করুন।
গ্রুপ অ্যানিমেশনের জন্য performBatchUpdates ব্যবহার করুন: collectionView.performBatchUpdates { insertItems, deleteItems, reloadItems }। নিরাপদ এবং অ্যানিমেটেড আপডেটের জন্য UICollectionViewDiffableDataSource ব্যবহার করুন: dataSource.apply(snapshot, animatingDifferences: true) কল করুন — ম্যানুয়াল insert/delete ছাড়াই সমস্ত পরিবর্তন স্বয়ংক্রিয়ভাবে গণনা এবং প্রয়োগ হবে।
SwiftUI-এ, UICollectionView-এর সমতুল্য হল LazyVGrid এবং LazyHGrid (iOS 14+)। SwiftUI Grid লেখা সহজ (ঘোষণামূলক সিনট্যাক্স) কিন্তু ৫০০+ উপাদান এবং লেআউট কাস্টমাইজেশনের জন্য কর্মক্ষমতায় UICollectionView-এর থেকে পিছিয়ে। জটিল সংগ্রহের জন্য UIViewRepresentable-এর মাধ্যমে UICollectionView ব্যবহার করুন। IT Sectr প্রকল্পে, আমরা ক্যাটালগ এবং গ্যালারির জন্য UICollectionView বেছে নিই এবং সরল স্ক্রিনের জন্য SwiftUI Grid বেছে নিই।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।