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 */; };
|
D2A514672213885800345BFB /* StandardHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A514662213885800345BFB /* StandardHeaderView.swift */; };
|
||||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; };
|
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; };
|
||||||
D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.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, ); }; };
|
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 */; };
|
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; };
|
||||||
D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = "<group>"; };
|
||||||
@ -475,6 +479,8 @@
|
|||||||
B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */,
|
B8200E182281DC1A007245F4 /* ProgressBarWithLabel.swift */,
|
||||||
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
|
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
|
||||||
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */,
|
D2A638FC22CA98280052ED1F /* HeadlineBody.swift */,
|
||||||
|
D2A6390022CBB1820052ED1F /* Carousel.swift */,
|
||||||
|
D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = Molecules;
|
path = Molecules;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -951,6 +957,8 @@
|
|||||||
01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */,
|
01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */,
|
||||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||||
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */,
|
||||||
|
D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */,
|
||||||
|
D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */,
|
||||||
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */,
|
||||||
016A1071228122180009D605 /* SwitchLineItem.swift in Sources */,
|
016A1071228122180009D605 /* SwitchLineItem.swift in Sources */,
|
||||||
D29DF29521E7ADB8003B2FB9 /* ProgrammaticScrollViewController.m 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,
|
@"image": MFLoadImageView.class,
|
||||||
@"leftRightLabelView": LeftRightLabelView.class,
|
@"leftRightLabelView": LeftRightLabelView.class,
|
||||||
@"moduleMolecule": ModuleMolecule.class,
|
@"moduleMolecule": ModuleMolecule.class,
|
||||||
@"headlineBody": HeadlineBody.class
|
@"headlineBody": HeadlineBody.class,
|
||||||
|
@"carousel": Carousel.class,
|
||||||
|
@"carouselItem": MoleculeCollectionViewCell.class
|
||||||
} mutableCopy];
|
} mutableCopy];
|
||||||
});
|
});
|
||||||
return mapping;
|
return mapping;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user