fiddling with three layer

This commit is contained in:
Pfeil, Scott Robert 2020-04-07 15:29:23 -04:00
parent d393098fcd
commit d53b212241
7 changed files with 348 additions and 137 deletions

View File

@ -249,6 +249,7 @@
D264FA8C243BCD8E00D98315 /* CollectionTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */; };
D264FA8E243BCD9A00D98315 /* CollectionTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */; };
D264FA90243BCE6800D98315 /* ThreeLayerCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */; };
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D264FAA0243CF66B00D98315 /* ContainerCollectionReusableView.swift */; };
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */; };
@ -654,6 +655,7 @@
D264FA8B243BCD8E00D98315 /* CollectionTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTemplateModel.swift; sourceTree = "<group>"; };
D264FA8D243BCD9A00D98315 /* CollectionTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionTemplate.swift; sourceTree = "<group>"; };
D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerCollectionViewController.swift; sourceTree = "<group>"; };
D264FAA0243CF66B00D98315 /* ContainerCollectionReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerCollectionReusableView.swift; sourceTree = "<group>"; };
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
D26C5A6A23F4A40D007AEECE /* ListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModel.swift; sourceTree = "<group>"; };
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
@ -1477,6 +1479,7 @@
D29DF2CD21E7C104003B2FB9 /* MFLoadingViewController.m */,
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */,
D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */,
D264FAA0243CF66B00D98315 /* ContainerCollectionReusableView.swift */,
D264FA8F243BCE6800D98315 /* ThreeLayerCollectionViewController.swift */,
D2C521A823EDE79E00CA2634 /* ViewController.swift */,
D2A92881241AAB67004E01C6 /* ScrollingViewController.swift */,
@ -2029,6 +2032,7 @@
D21B7F77243BB70700051ABF /* MoleculeCollectionItemModel.swift in Sources */,
D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */,
011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */,
D264FAA1243CF66B00D98315 /* ContainerCollectionReusableView.swift in Sources */,
D260106323D0C05000764D80 /* StackItemModel.swift in Sources */,
D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */,
D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */,

View File

@ -112,7 +112,9 @@ import Foundation
// Other Items
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeStackItem.self, viewModelClass: MoleculeStackItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: StackItem.self, viewModelClass: StackItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: CarouselItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeCollectionViewCell.self, viewModelClass: MoleculeCollectionItemModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: CarouselItem.self, viewModelClass: CarouselItemModel.self)
// Other Container Molecules
MoleculeObjectMapping.shared()?.register(viewClass: MoleculeHeaderView.self, viewModelClass: MoleculeHeaderModel.self)

View File

@ -35,4 +35,11 @@ import Foundation
self.color = color
self.label = label
}
private enum CodingKeys: String, CodingKey {
case backgroundColor
case label
case percent
case color
}
}

View File

@ -11,5 +11,167 @@ import Foundation
@objc open class CollectionTemplate: ThreeLayerCollectionViewController, TemplateProtocol {
public typealias TemplateModel = CollectionTemplateModel
public var templateModel: CollectionTemplateModel?
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (CollectionItemModelProtocol & MoleculeModelProtocol))]?
var observer: NSKeyValueObservation?
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
open override func parsePageJSON() throws {
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
open override var loadObject: MVMCoreLoadObject? {
didSet {
guard loadObject != oldValue else { return }
updateRequiredModules()
observer?.invalidate()
if let newObject = loadObject {
observer = newObject.observe(\MVMCoreLoadObject.pageJSON, options: [.old, .new]) { [weak self] object, change in
self?.updateRequiredModules()
}
}
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
open override func viewForTop() -> UIView? {
guard let headerModel = templateModel?.header,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar)
else { return super.viewForTop() }
// Temporary, Default the horizontal padding
if var container = templateModel?.header as? ContainerModelProtocol, container.useHorizontalMargins == nil {
container.useHorizontalMargins = true
}
return molecule
}
override open func viewForBottom() -> UIView? {
guard let footerModel = templateModel?.footer,
let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar)
else { return super.viewForBottom() }
return molecule
}
open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject>) -> Bool {
guard super.shouldFinishProcessingLoad(loadObject, error: error) else { return false }
// This template requires atleast one of the three layers.
if templateModel?.header == nil,
templateModel?.molecules?.count ?? 0 == 0,
templateModel?.footer == nil,
let errorObject = MVMCoreErrorObject(title: nil, message: MVMCoreGetterUtility.hardcodedString(withKey: HardcodedErrorUnableToProcess), messageToLog: "Collection template requires atleast one of the following: header, footer, molecules", code: CoreUIErrorCode.ErrorCodeListMolecule.rawValue, domain: ErrorDomainNative, location: String(describing: self)) {
error.pointee = errorObject
return false
}
return true
}
open override func handleNewData() {
super.handleNewData()
setup()
registerCells()
}
//--------------------------------------------------
// MARK: - Collection
//--------------------------------------------------
open override func registerCells() {
super.registerCells()
guard let moleculesInfo = moleculesInfo else { return }
for moleculeInfo in moleculesInfo {
collectionView?.register(moleculeInfo.class, forCellWithReuseIdentifier: moleculeInfo.identifier)
}
}
open override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return moleculesInfo?.count ?? 0
}
open override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
open override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let moleculeInfo = moleculesInfo?[indexPath.row]
else { return UICollectionViewCell() }
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath)
(cell as? MoleculeViewProtocol)?.reset()
(cell as? MoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegateObjectIVar, nil)
(cell as? MVMCoreViewProtocol)?.updateView(view.bounds.width)
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
cell.layoutIfNeeded()
return cell
}
//--------------------------------------------------
// MARK: - Convenience
//--------------------------------------------------
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with item: (CollectionItemModelProtocol & MoleculeModelProtocol)?) -> (identifier: String, class: AnyClass, molecule: CollectionItemModelProtocol & MoleculeModelProtocol)? {
guard let item = item,
let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(item) else { return nil }
let moleculeName = moleculeClass.nameForReuse(with: item, delegateObjectIVar) ?? item.moleculeName
return (moleculeName, moleculeClass, item)
}
/// Sets up the molecule list and ensures no errors loading all content.
func getMoleculeInfoList() -> [(identifier: String, class: AnyClass, molecule: (CollectionItemModelProtocol & MoleculeModelProtocol))]? {
var moleculeList: [(identifier: String, class: AnyClass, molecule: CollectionItemModelProtocol & MoleculeModelProtocol)] = []
if let molecules = templateModel?.molecules {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule) {
moleculeList.append(info)
}
}
}
return moleculeList.count > 0 ? moleculeList : nil
}
/// Sets up the header, footer, molecule list and ensures no errors loading all content.
func setup() {
moleculesInfo = getMoleculeInfoList()
}
/// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map.
open func updateRequiredModules() {
if let requiredModules = requiredModules(), let pageType = pageType {
MVMCoreViewControllerMappingObject.shared()?.addRequiredModules(toMapping: requiredModules, forPageType: pageType)
}
}
/// Gets modules required by the loadObject.pageJSON.
open func requiredModules() -> [Any]? {
var modules: [String]? = []
var errors: [MVMCoreErrorObject]? = nil
MoleculeObjectMapping.addRequiredModules(for: templateModel?.header, delegateObjectIVar, moduleList: &modules, errorList: &errors)
MoleculeObjectMapping.addRequiredModules(for: templateModel?.footer, delegateObjectIVar, moduleList: &modules, errorList: &errors)
if let molecules = templateModel?.molecules {
for molecule in molecules {
MoleculeObjectMapping.addRequiredModules(for: molecule, delegateObjectIVar, moduleList: &modules, errorList: &errors)
}
}
return modules
}
}

View File

@ -0,0 +1,25 @@
//
// ContainerCollectionReusableView.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 4/7/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public class ContainerCollectionReusableView: UICollectionReusableView {
var view: UIView?
var topConstraint: NSLayoutConstraint?
var bottomConstraint: NSLayoutConstraint?
public func addAndContain(view: UIView) {
self.view?.removeFromSuperview()
view.setContentCompressionResistancePriority(.required, for: .vertical)
addSubview(view)
self.view = view
let constraints = NSLayoutConstraint.constraintPinSubview(toSuperview: view)
topConstraint = constraints?[ConstraintTop] as? NSLayoutConstraint
bottomConstraint = constraints?[ConstraintBot] as? NSLayoutConstraint
}
}

View File

@ -8,19 +8,17 @@
import Foundation
@objc open class ThreeLayerCollectionViewController: ScrollingViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@objc open class ThreeLayerCollectionViewController: ScrollingViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
public var collectionView: UICollectionView?
// The three main views
private var topView: UIView?
private var bottomView: UIView?
private var headerView: UIView?
private var footerView: UIView?
private var safeAreaView: UIView?
private var headerView: ContainerCollectionReusableView?
private var footerView: ContainerCollectionReusableView?
var useMargins: Bool = true
public var bottomViewOutsideOfScrollArea: Bool = false
private var topViewBottomConstraint: NSLayoutConstraint?
private var bottomViewTopConstraint: NSLayoutConstraint?
private let headerID = "header"
private let footerID = "footer"
//MARK: - MFViewController
open override func updateViews() {
@ -28,7 +26,7 @@ import Foundation
let width = view.bounds.width
if let topView = topView as? MVMCoreViewProtocol {
topView.updateView(width)
//showHeader(width)
// showHeader(width)
}
if let bottomView = bottomView as? MVMCoreViewProtocol {
bottomView.updateView(width)
@ -39,8 +37,8 @@ import Foundation
open override func handleNewData() {
super.handleNewData()
//createViewForTableHeader()
//createViewForTableFooter()
createViewForTableHeader()
createViewForTableFooter()
collectionView?.reloadData()
}
@ -74,11 +72,11 @@ import Foundation
return 0
}
/*open override func updateViewConstraints() {
open override func updateViewConstraints() {
super.updateViewConstraints()
guard let tableView = collectionView else { return }
let minimumSpace: CGFloat = minimumFillSpace()
var currentSpace: CGFloat = 0
var totalMinimumSpace: CGFloat = 0
@ -86,48 +84,43 @@ import Foundation
var fillTop = false
if spaceBelowTopView() == nil, headerView != nil {
fillTop = true
currentSpace += topViewBottomConstraint?.constant ?? 0
currentSpace += headerView?.bottomConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace
}
var fillBottom = false
if spaceAboveBottomView() == nil, !bottomViewOutsideOfScrollArea, footerView != nil {
if spaceAboveBottomView() == nil, footerView != nil {
fillBottom = true
currentSpace += bottomViewTopConstraint?.constant ?? 0
currentSpace += footerView?.topConstraint?.constant ?? 0
totalMinimumSpace += minimumSpace
}
guard fillTop || fillBottom else { return }
let newSpace = MVMCoreUIUtility.getVariableConstraintHeight(currentSpace, in: tableView, minimumHeight: totalMinimumSpace)
// If the bottom view is outside of the scroll, then only the top view constraint is being used, so we have to double it to account for the bottom constraint not being there when we compare to the new value.
var currentSpaceForCompare: CGFloat = currentSpace
if fillTop && bottomViewOutsideOfScrollArea {
if fillTop {
currentSpaceForCompare = currentSpace * 2;
}
let width = view.bounds.width
if !MVMCoreGetterUtility.cgfequalwiththreshold(newSpace, currentSpaceForCompare, 0.1) {
if fillTop && fillBottom {
// space both
let half = newSpace / 2
topViewBottomConstraint?.constant = half
bottomViewTopConstraint?.constant = half
showHeader(width)
showFooter(width)
headerView?.bottomConstraint?.constant = half
footerView?.topConstraint?.constant = half
collectionView?.invalidateIntrinsicContentSize()
} else if fillTop {
// Only top is spaced (half the size if the bottom view is out of the scroll because it needs to be sized as if there are two spacers but there is only one.
if bottomViewOutsideOfScrollArea {
topViewBottomConstraint?.constant = newSpace / 2
} else {
topViewBottomConstraint?.constant = newSpace
}
showHeader(width)
headerView?.bottomConstraint?.constant = newSpace
collectionView?.invalidateIntrinsicContentSize()
} else if fillBottom {
// Only bottom is spaced.
bottomViewTopConstraint?.constant = newSpace
showFooter(width)
print("newSpace \(newSpace)")
footerView?.topConstraint?.constant = newSpace
collectionView?.invalidateIntrinsicContentSize()
}
}
}
@ -135,113 +128,99 @@ import Foundation
//MARK: - Header Footer
/// Gets the top view and adds it to a spacing view, headerView, and then calls showHeader.
open func createViewForTableHeader() {
let topView = viewForTop()
guard let topView = viewForTop() else {
self.topView = nil
self.headerView = nil
return
}
self.topView = topView
let headerView = MVMCoreUICommonViewsUtility.commonView()
headerView.addSubview(topView)
topView.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
topView.leftAnchor.constraint(equalTo: headerView.leftAnchor).isActive = true
headerView.rightAnchor.constraint(equalTo: topView.rightAnchor).isActive = true
topViewBottomConstraint = headerView.bottomAnchor.constraint(equalTo: topView.bottomAnchor, constant: spaceBelowTopView() ?? 0)
topViewBottomConstraint?.isActive = true
self.headerView = headerView
showHeader(nil)
}
/// Gets the bottom view and adds it to a spacing view, footerView, and then calls showFooter.
open func createViewForTableFooter() {
let bottomView = viewForBottom()
guard let bottomView = viewForBottom() else {
self.bottomView = nil
self.footerView = nil
return
}
self.bottomView = bottomView
let footerView = MVMCoreUICommonViewsUtility.commonView()
footerView.addSubview(bottomView)
bottomViewTopConstraint = bottomView.topAnchor.constraint(equalTo: footerView.topAnchor, constant: spaceAboveBottomView() ?? 0)
bottomViewTopConstraint?.isActive = true
bottomView.leftAnchor.constraint(equalTo: footerView.leftAnchor).isActive = true
footerView.rightAnchor.constraint(equalTo: bottomView.rightAnchor).isActive = true
footerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
self.footerView = footerView
showFooter(nil)
}
/// Takes the current headerView and adds it to the tableHeaderView
func showHeader(_ sizingWidth: CGFloat?) {
headerView?.removeFromSuperview()
tableView?.tableHeaderView = nil
guard let headerView = headerView else {
return
}
// This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
MVMCoreUIUtility.sizeView(toFit: headerView)
let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height))
tableHeaderView.addSubview(headerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
tableView?.tableHeaderView = tableHeaderView
}
/// Takes the current footerView and adds it to the tableFooterView
func showFooter(_ sizingWidth: CGFloat?) {
footerView?.removeFromSuperview()
safeAreaView?.removeFromSuperview()
guard let footerView = footerView, let tableView = tableView else {
return
}
if bottomViewOutsideOfScrollArea {
// put bottom view outside of scrolling area.
bottomConstraint?.isActive = false
view.addSubview(footerView)
footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
safeAreaView?.backgroundColor = bottomView?.backgroundColor
} else {
bottomConstraint?.isActive = true
var y: CGFloat?
if let tableFooterView = tableView.tableFooterView {
// if footer already exists, use the same y location to avoid strange moving animation
y = tableFooterView.frame.minY
}
// This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
MVMCoreUIUtility.sizeView(toFit: footerView)
let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
tableFooterView.addSubview(footerView)
NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
tableView.tableFooterView = tableFooterView
}
}*/
// /// Takes the current headerView and adds it to the tableHeaderView
// func showHeader(_ sizingWidth: CGFloat?) {
// headerView?.removeFromSuperview()
// tableView?.tableHeaderView = nil
// guard let headerView = headerView else {
// return
// }
//
// // This extra view is needed because of the wonkiness of apple's table header. Things breaks if using autolayout.
// headerView.setNeedsLayout()
// headerView.layoutIfNeeded()
// MVMCoreUIUtility.sizeView(toFit: headerView)
// let tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: MVMCoreUIUtility.getWidth(), height: headerView.frame.height))
// tableHeaderView.addSubview(headerView)
// NSLayoutConstraint.constraintPinSubview(toSuperview: headerView)
// tableView?.tableHeaderView = tableHeaderView
// }
//
// /// Takes the current footerView and adds it to the tableFooterView
// func showFooter(_ sizingWidth: CGFloat?) {
// footerView?.removeFromSuperview()
// safeAreaView?.removeFromSuperview()
// guard let footerView = footerView, let tableView = tableView else {
// return
// }
//
// if bottomViewOutsideOfScrollArea {
// // put bottom view outside of scrolling area.
// bottomConstraint?.isActive = false
// view.addSubview(footerView)
// footerView.topAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true
// footerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
// view.rightAnchor.constraint(equalTo: footerView.rightAnchor).isActive = true
// view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: footerView.bottomAnchor).isActive = true
// safeAreaView = MVMCoreUICommonViewsUtility.getAndSetupSafeAreaView(on: view)
// safeAreaView?.backgroundColor = bottomView?.backgroundColor
// } else {
// bottomConstraint?.isActive = true
// var y: CGFloat?
// if let tableFooterView = tableView.tableFooterView {
// // if footer already exists, use the same y location to avoid strange moving animation
// y = tableFooterView.frame.minY
// }
//
// // This extra view is needed because of the wonkiness of apple's table footer. Things breaks if using autolayout.
// MVMCoreUIUtility.sizeView(toFit: footerView)
// let tableFooterView = UIView(frame: CGRect(x: 0, y: y ?? 0, width: MVMCoreUIUtility.getWidth(), height: footerView.frame.height))
// tableFooterView.addSubview(footerView)
// NSLayoutConstraint.constraintPinSubview(toSuperview: footerView)
// tableView.tableFooterView = tableFooterView
// }
// }
//MARK: - Functions to subclass
/// Subclass for a top view.
open func viewForTop() -> UIView {
let view = MVMCoreUICommonViewsUtility.commonView()
// Small height is needed to stop apple from adding padding for grouped tables when no header.
view.heightAnchor.constraint(equalToConstant: 1).isActive = true
return view
open func viewForTop() -> UIView? {
return nil
}
/// Subclass for a bottom view.
open func viewForBottom() -> UIView {
// Default spacing is standard when no buttons.
let view = MVMCoreUICommonViewsUtility.commonView()
view.heightAnchor.constraint(equalToConstant: PaddingDefaultVerticalSpacing).isActive = true
return view
open func viewForBottom() -> UIView? {
return nil
}
open func createCollectionViewLayout() -> UICollectionViewLayout {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
return layout
}
open func createCollectionView() -> UICollectionView {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 1
layout.minimumInteritemSpacing = 0
let collection = UICollectionView(frame: .zero, collectionViewLayout: layout)
let collection = UICollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout())
collection.translatesAutoresizingMaskIntoConstraints = false
collection.dataSource = self
collection.delegate = self
@ -259,19 +238,20 @@ import Foundation
//MARK: - Collection
public func registerCells() {
collectionView?.register(MoleculeCollectionViewCell.self, forCellWithReuseIdentifier: "collectionItem")
open func registerCells() {
collectionView?.register(ContainerCollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerID)
collectionView?.register(ContainerCollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: footerID)
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 0
}
public func numberOfSections(in collectionView: UICollectionView) -> Int {
open func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionItem", for: indexPath) as! MoleculeCollectionViewCell
let labelModel = LabelModel(text: "hello")
let model = MoleculeCollectionItemModel(with: labelModel)
@ -279,11 +259,42 @@ import Foundation
return cell
}
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 200, height: 200)
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
guard let view = headerView ?? topView,
section == 0 else { return .zero }
// Use this view to calculate the optimal size based on the collection view's width
return view.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height),
withHorizontalFittingPriority: .required, // Width is fixed
verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
}
open func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
(cell as? CarouselItem)?.setPeaking(false, animated: false)
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
guard let view = footerView ?? bottomView,
section == numberOfSections(in: collectionView) - 1 else { return .zero }
// Use this view to calculate the optimal size based on the collection view's width
let size = view.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height),
withHorizontalFittingPriority: .required, // Width is fixed
verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
print("SIZEEE \(size.height) \(String(describing: footerView?.topConstraint?.constant))")
return size
}
open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
if (kind == UICollectionView.elementKindSectionFooter) {
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerID, for: indexPath) as! ContainerCollectionReusableView
footerView.addAndContain(view: bottomView!)
footerView.topConstraint?.constant = spaceAboveBottomView() ?? 0
self.footerView = footerView
return footerView
} else if (kind == UICollectionView.elementKindSectionHeader) {
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerID, for: indexPath) as! ContainerCollectionReusableView
headerView.addAndContain(view: topView!)
headerView.bottomConstraint?.constant = spaceBelowTopView() ?? 0
self.headerView = headerView
return headerView
}
fatalError()
}
}

View File

@ -164,7 +164,7 @@
CGFloat topInset = scrollview.contentInset.top;
CGFloat bottomInset = scrollview.contentInset.bottom;
if (scrollview.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) {
if (scrollview.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic || scrollview.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAlways) {
topInset = scrollview.adjustedContentInset.top;
bottomInset = scrollview.adjustedContentInset.bottom;
}