mvm_core_ui/MVMCoreUI/Molecules/Carousel.swift
Pfeil, Scott Robert 033cf878a6 carousel
2019-07-03 13:18:27 -04:00

129 lines
5.4 KiB
Swift

//
// Carousel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 7/2/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
open class Carousel: ViewConstrainingView {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
var currentIndex = 1
var numberOfCards = 0
var molecules: [[AnyHashable : Any]]?
var collectionViewHeight: NSLayoutConstraint?
open override func setupView() {
super.setupView()
guard collectionView.superview == nil else {
return
}
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.dataSource = self
collectionView.delegate = self
collectionView.showsHorizontalScrollIndicator = false
collectionView.backgroundColor = .clear
addSubview(collectionView)
pinView(toSuperView: collectionView)
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300)
collectionViewHeight?.isActive = true
}
/// Registers the cells with the collection view
func registerCells(with json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) {
if let molecules = json?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] {
for molecule in molecules {
if let info = getMoleculeInfo(with: molecule, delegateObject: delegateObject) {
collectionView.register(info.class, forCellWithReuseIdentifier: info.identifier)
}
}
}
}
/// Updates the layout being used
func setupLayout(with json:[AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = json?["spacing"] as? CGFloat ?? 0
layout.minimumInteritemSpacing = 0
//layout.itemSize = CGSize(width: 300, height: 200)
collectionView.collectionViewLayout = layout
}
func prepareMolecules(_ json: [AnyHashable : Any]?) {
guard let newMolecules = json?.optionalArrayForKey(KeyMolecules) as? [[AnyHashable: Any]] else {
numberOfCards = 0
molecules = nil
return
}
numberOfCards = newMolecules.count
molecules = newMolecules
if json?.boolForKey("loop") ?? false && newMolecules.count > 2 {
// Sets up the row data with a buffer cell on each side (for illusion of endless scroll... also has one more buffer cell on right since we can peek that cell).
molecules?.insert(newMolecules.last!, at: 0)
molecules?.append(newMolecules.first!)
molecules?.append(newMolecules[1])
}
}
open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
collectionViewHeight?.constant = json?.optionalCGFloatForKey("height") ?? 300
registerCells(with: json, delegateObject: delegateObject)
setupLayout(with: json, delegateObject: delegateObject)
prepareMolecules(json)
collectionView.reloadData()
// Go to starting cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic.
collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: .left, animated: false)
collectionView.layoutIfNeeded()
}
open override func setAsMolecule() {
super.setAsMolecule()
updateViewHorizontalDefaults = false
}
// MARK: - Convenience
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: [AnyHashable: Any])? {
guard let molecule = molecule,
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule),
let moleculeName = moleculeClass.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) else {
return nil
}
return (moleculeName, moleculeClass, molecule)
}
}
extension Carousel: UICollectionViewDelegate {
}
extension Carousel: UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return molecules?.count ?? 0
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let molecule = molecules?[indexPath.row],
let moleculeInfo = getMoleculeInfo(with: molecule, delegateObject: nil) else {
return UICollectionViewCell()
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath)
if let protocolCell = cell as? MVMCoreUIMoleculeViewProtocol {
protocolCell.reset?()
protocolCell.setWithJSON(moleculeInfo.molecule, delegateObject: nil, additionalData: nil)
protocolCell.updateView(collectionView.bounds.width)
}
return cell
}
}