129 lines
5.4 KiB
Swift
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
|
|
}
|
|
}
|