carousel
This commit is contained in:
parent
f6021bb382
commit
033cf878a6
@ -162,6 +162,8 @@
|
||||
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* StandardHeaderView.swift */; };
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; };
|
||||
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; };
|
||||
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; };
|
||||
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; };
|
||||
D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
||||
@ -335,6 +337,8 @@
|
||||
D2A514662213885800345BFB /* StandardHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardHeaderView.swift; sourceTree = "<group>"; };
|
||||
D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerViewController.swift; sourceTree = "<group>"; };
|
||||
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = "<group>"; };
|
||||
D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = "<group>"; };
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = "<group>"; };
|
||||
D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = "<group>"; };
|
||||
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||
@ -475,6 +479,8 @@
|
||||
B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */,
|
||||
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
|
||||
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */,
|
||||
D2A6390022CBB1820052ED1F /* Carousel.swift */,
|
||||
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
|
||||
);
|
||||
path = Molecules;
|
||||
sourceTree = "<group>";
|
||||
@ -951,6 +957,8 @@
|
||||
01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */,
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
||||
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */,
|
||||
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */,
|
||||
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
||||
016A1071228122180009D605 /* SwitchLineItem.swift in Sources */,
|
||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m in Sources */,
|
||||
|
||||
128
MVMCoreUI/Molecules/Carousel.swift
Normal file
128
MVMCoreUI/Molecules/Carousel.swift
Normal file
@ -0,0 +1,128 @@
|
||||
//
|
||||
// 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
|
||||
}
|
||||
}
|
||||
65
MVMCoreUI/Molecules/MoleculeCollectionViewCell.swift
Normal file
65
MVMCoreUI/Molecules/MoleculeCollectionViewCell.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// MoleculeCollectionViewCell.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 7/2/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class MoleculeCollectionViewCell: UICollectionViewCell, MVMCoreUIMoleculeViewProtocol, MoleculeListCellProtocol {
|
||||
open var molecule: (UIView & MVMCoreUIMoleculeViewProtocol)?
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
setupView()
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
setupView()
|
||||
}
|
||||
|
||||
public func setupView() {
|
||||
}
|
||||
|
||||
public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
guard let json = json, let moleculeJSON = json.optionalDictionaryForKey(KeyMolecule) else {
|
||||
return
|
||||
}
|
||||
if molecule == nil {
|
||||
if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject, constrainIfNeeded: true) {
|
||||
contentView.addSubview(moleculeView)
|
||||
let standardConstraints = (moleculeView as? MVMCoreUIViewConstrainingProtocol)?.useStandardConstraints?() ?? true
|
||||
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: moleculeView, useMargins: standardConstraints).values))
|
||||
if standardConstraints {
|
||||
let constraint = contentView.heightAnchor.constraint(equalToConstant: 80)
|
||||
constraint.priority = .defaultLow
|
||||
constraint.isActive = true
|
||||
}
|
||||
molecule = moleculeView
|
||||
}
|
||||
} else {
|
||||
molecule?.setWithJSON(moleculeJSON, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
if let castView = molecule as? MVMCoreUIViewConstrainingProtocol {
|
||||
let standardConstraints = castView.useStandardConstraints?() ?? true
|
||||
castView.shouldSetHorizontalMargins?(!standardConstraints)
|
||||
castView.shouldSetVerticalMargins?(!standardConstraints)
|
||||
}
|
||||
|
||||
backgroundColor = molecule?.backgroundColor
|
||||
}
|
||||
|
||||
public static func name(forReuse molecule: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
guard let molecule = molecule?.optionalDictionaryForKey(KeyMolecule) else {
|
||||
return nil
|
||||
}
|
||||
return MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName)
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -48,7 +48,9 @@
|
||||
@"image": MFLoadImageView.class,
|
||||
@"leftRightLabelView": LeftRightLabelView.class,
|
||||
@"moduleMolecule": ModuleMolecule.class,
|
||||
@"headlineBody": HeadlineBody.class
|
||||
@"headlineBody": HeadlineBody.class,
|
||||
@"carousel": Carousel.class,
|
||||
@"carouselItem": MoleculeCollectionViewCell.class
|
||||
} mutableCopy];
|
||||
});
|
||||
return mapping;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user