UICollectionView with simple usage for cell's dynamic size
- Vertical/Horizontal scrolling sections.
- Left align section.
- Dynamic height for cells.
- Dynamic width for cells in horizontal sections (optional).
- Scaling effect on select cell.
- Columns number is settable.
- Placeholder view for empty data.
# platform :ios, '13.0'
target 'MyApp' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for MyApp
pod 'DHCollectionView'
end- First you should create your own cell and inherit from DHCell:
import DHCollectionView
final class MyCell: DHCell {
func update(with data: DHCellModelData?) {
guard let data = data as? MyCellData else { return }
//below update your cell data
}
}MyCellData looks like:
import DHCollectionView
struct MyCellData: DHCellModelData {
//your data properties
}- Creating header/footer is equal to cell creating:
import DHCollectionView
final class MyHeader: DHSupplementaryElement {
func update(with data: DHSupplementaryElementModelData?) {
guard let data = data as? MyHeaderData else { return }
//below update your header data
}
}import DHCollectionView
struct MyHeaderData: DHSupplementaryElementModelData {
//your data properties
}-
Add
DHCollectionViewto subviews of yourUIViewController's view. -
For displaying
MyCellandMyHeaderonDHCollectionViewmake a section -DHSectionWrapper, cellModels -[DHCellModel]and supplementaryElementModels -DHSupplementaryElementsModel:
import DHCollectionView
final class MyViewController: UIViewController {
private var dataModels: [DataModel]?
private lazy var collectionView = DHCollectionView()
override func loadView() {
view = collectionView
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateViews()
}
private func updateViews() {
guard let dataModels, !dataModels.isEmpty else {
collectionView.showPlaceholder(
withImage: UIImage(named: "placeholderImage"),
withTitle: "placeholder title",
withMessage: "placeholder message"
)
return
}
let cellModels = dataModels.map {
DHCellModel(
data: MyCellData(),
cellType: MyCell.self
)
}
let headerModel = DHHeaderModel(
data: MyHeaderData(),
viewType: MyHeader.self
)
let section = DHSectionWrapper(
sectionId: 0,
sectionInsets: DHSectionInsets(top: 0, left: 16, bottom: 0, right: 16),
scrollDirection: .vertical(align: .center(columns: 2)),
spacing: 16,
hasScalingEffectOnSelect: true
)
let sectionData = DHSectionData(
cellModels: cellModels,
supplementaryElementModels:
DHSupplementaryElementsModel(
header: headerModel,
footer: nil
)
)
collectionView.display(withSectionsData: [section : sectionData])
}
}-
NOTE: Sections will be sorted by 'sectionId' property. 'sectionId' should be a unique across different sections (sections with same 'sectionId' are equal). -
If no data show placeholder view:
collectionView.showPlaceholder(
withImage: UIImage(named: "placeholderImage"),
withTitle: "placeholder title",
withMessage: "placeholder message"
)- If there is no need to use a header or footer:
let sectionData = DHSectionData(
cellModels: cellModels,
supplementaryElementModels: .noModel
)-
If there are many sections make a
enum CustomSectionwithIntRawValue and conforms toCaseIterable. If sections count is dynamic make your sections insideforloop. -
DHCollectionViewproperties:var didSelectItemAt: ((_ model: DHCellModel?, _ indexPath: DHIndexPath) -> ())?var willDisplayCellAt: ((_ cell: UICollectionViewCell, _ indexPath: DHIndexPath) -> ())?var didEndDisplayingCellAt: ((_ cell: UICollectionViewCell, _ indexPath: DHIndexPath) -> ())?var willDisplaySupplementaryViewAt: ((_ view: UICollectionReusableView, _ kind: DHSupplementaryElementKind, _ indexPath: DHIndexPath) -> ())?var didEndDisplayingSupplementaryViewAt: ((_ view: UICollectionReusableView, _ kind: DHSupplementaryElementKind, _ indexPath: DHIndexPath) -> ())?var didScroll: ((_ scrollView: UIScrollView) -> ())?var supplementaryViewHandler: ((_ view: UICollectionReusableView, _ kind: DHSupplementaryElementKind, _ indexPath: DHIndexPath) -> ())?- to configure supplementary view.var cellHandler: ((_ cell: UICollectionViewCell, _ indexPath: DHIndexPath) -> ())?- to configure cell view.var onTopRefresh: (() -> ())?- to add refresh control to view.private(set) var collectionView: UICollectionView- to configure collection view.private(set) var refreshControl: UIRefreshControl- to configure refresh control view.private(set) var placeholderView: UIView- to configure placeholder view.private(set) var placeholderImageView: UIImageView- to configure placeholder image view.private(set) var placeholderLabel: UILabel- to configure placeholder message label view.
-
DHCollectionViewmethods:func display(withSectionsData sectionsData: [DHSectionWrapper: DHSectionData])- display on collection view given data (sections will be sorted bysectionIdproperty).func showPlaceholder(withImage image: UIImage?, withTitle title: String?, withMessage message: String?)- show placeholder view with custom image, title and message.func scrollToBottom()- scroll to bottom side of collection view.
-
You can customize these properties of the
DHCollectionView:backgroundColorplaceholderImageViewHeightplaceholderImageViewWidthrefreshControlTintColorplaceholderViewBackgroundColorplaceholderTitleLabelTextColorplaceholderTitleLabelTextAlignmentplaceholderTitleLabelFontplaceholderMessageLabelTextColorplaceholderMessageLabelTextAlignmentplaceholderMessageLabelFontcellEstimatedSizesupplementaryItemsEstimatedSizedownScale- the scale of scaling effect on select cell.
-
You can change them through each instance of
DHCollectionViewor viaUIAppearancelike this for example:
DHCollectionView.appearance().backgroundColor = .red
DHCollectionView.appearance().placeholderImageViewHeight = 200
DHCollectionView.appearance().placeholderImageViewWidth = 200