Add action to collection cells
make paging configurable for carousel. add insets to carousel use button helper function for collection and table cell.
This commit is contained in:
parent
ce5b5a77ca
commit
57d7a5f7cc
@ -33,7 +33,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
public var disabledIndicatorColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
public var indicatorColor: Color = Color(uiColor: .mvmBlack)
|
||||
public var indicatorColor_inverted: Color = Color(uiColor: .mvmWhite)
|
||||
public var position: Float?
|
||||
public var position: CGFloat?
|
||||
|
||||
/// Allows sendActions() to trigger even if index is already at min/max index.
|
||||
public var alwaysSendAction = false
|
||||
@ -79,7 +79,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
||||
self.inverted = inverted
|
||||
}
|
||||
|
||||
if let position = try typeContainer.decodeIfPresent(Float.self, forKey: .position) {
|
||||
if let position = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .position) {
|
||||
self.position = position
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,12 @@ import Foundation
|
||||
open override class var identifier: String {
|
||||
return "collectionItem"
|
||||
}
|
||||
|
||||
public var action: ActionModelProtocol?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case action
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
public override func setDefaults() {
|
||||
@ -35,10 +41,14 @@ import Foundation
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
try super.encode(to: encoder)
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,8 +19,14 @@ public protocol CarouselPageControlProtocol {
|
||||
|
||||
open class Carousel: View {
|
||||
|
||||
public let collectionView = CollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||
|
||||
public let collectionView: CollectionView = {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .horizontal
|
||||
layout.minimumInteritemSpacing = 0
|
||||
layout.minimumLineSpacing = 0
|
||||
return CollectionView(frame: .zero, collectionViewLayout: layout)
|
||||
}()
|
||||
|
||||
/// The current index of the collection view. Includes dummy cells when looping.
|
||||
public var currentIndex = 0
|
||||
|
||||
@ -36,13 +42,13 @@ open class Carousel: View {
|
||||
open var numberOfPages = 0
|
||||
|
||||
/// The models for the molecules.
|
||||
var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]?
|
||||
public var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]?
|
||||
|
||||
/// The horizontal alignment of the cell in the collection view. Only noticeable if the itemWidthPercent is less than 100%.
|
||||
public var itemAlignment = UICollectionView.ScrollPosition.left
|
||||
|
||||
/// From 0-1. The item width as a percent of the carousel width.
|
||||
public var itemWidthPercent: Float = 1
|
||||
public var itemWidthPercent: CGFloat = 1
|
||||
|
||||
/// The height of the carousel. Default is 300.
|
||||
public var collectionViewHeight: NSLayoutConstraint?
|
||||
@ -51,7 +57,7 @@ open class Carousel: View {
|
||||
public var pagingView: (UIView & CarouselPageControlProtocol)?
|
||||
|
||||
/// If the carousel should loop after scrolling past the first and final cells.
|
||||
var loop = false
|
||||
public var loop = false
|
||||
|
||||
private var dragging = false
|
||||
|
||||
@ -81,6 +87,8 @@ open class Carousel: View {
|
||||
showPeaking(false)
|
||||
|
||||
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
||||
guard let model = model as? CarouselModel,
|
||||
(model.paging == true || model.loop == true) else { return }
|
||||
DispatchQueue.main.async {
|
||||
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: false)
|
||||
self.collectionView.layoutIfNeeded()
|
||||
@ -98,15 +106,23 @@ open class Carousel: View {
|
||||
collectionView.delegate = self
|
||||
addSubview(collectionView)
|
||||
bottomPin = NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)?[ConstraintBot] as? NSLayoutConstraint
|
||||
|
||||
collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300)
|
||||
collectionViewHeight?.isActive = false
|
||||
collectionViewHeight?.isActive = true
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
self.size = size
|
||||
|
||||
// Set insets for the carousel.
|
||||
var inset = UIEdgeInsets.zero
|
||||
let carouselModel = model as? CarouselModel
|
||||
if carouselModel?.useHorizontalMargins ?? false {
|
||||
inset.left = carouselModel?.leftPadding ?? Padding.Component.horizontalPaddingForSize(size)
|
||||
inset.right = carouselModel?.rightPadding ?? Padding.Component.horizontalPaddingForSize(size)
|
||||
}
|
||||
(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset = inset
|
||||
|
||||
// Update cells and re-layout.
|
||||
for cell in collectionView.visibleCells {
|
||||
(cell as? MVMCoreViewProtocol)?.updateView(size)
|
||||
@ -128,19 +144,19 @@ open class Carousel: View {
|
||||
collectionView.layer.borderColor = backgroundColor?.cgColor
|
||||
collectionView.layer.borderWidth = (carouselModel.border ?? false) ? 1 : 0
|
||||
backgroundColor = .white
|
||||
|
||||
registerCells(with: carouselModel, delegateObject: delegateObject)
|
||||
setupLayout(with: carouselModel)
|
||||
prepareMolecules(with: carouselModel)
|
||||
itemWidthPercent = (carouselModel.itemWidthPercent ?? 100) / 100
|
||||
(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing = carouselModel.spacing ?? 0
|
||||
|
||||
itemWidthPercent = carouselModel.itemWidthPercent / 100.0
|
||||
if let alignment = carouselModel.itemAlignment {
|
||||
itemAlignment = alignment
|
||||
}
|
||||
|
||||
if let height = carouselModel.height {
|
||||
collectionViewHeight?.constant = CGFloat(height)
|
||||
collectionViewHeight?.isActive = true
|
||||
collectionViewHeight?.constant = height
|
||||
}
|
||||
|
||||
registerCells(with: carouselModel, delegateObject: delegateObject)
|
||||
prepareMolecules(with: carouselModel)
|
||||
|
||||
setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject)
|
||||
|
||||
@ -153,16 +169,6 @@ open class Carousel: View {
|
||||
// MARK: - JSON Setters
|
||||
//--------------------------------------------------
|
||||
|
||||
/// Updates the layout being used
|
||||
func setupLayout(with carouselModel: CarouselModel?) {
|
||||
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.scrollDirection = .horizontal
|
||||
layout.minimumLineSpacing = CGFloat(carouselModel?.spacing ?? 1)
|
||||
layout.minimumInteritemSpacing = 0
|
||||
collectionView.collectionViewLayout = layout
|
||||
}
|
||||
|
||||
func prepareMolecules(with carouselModel: CarouselModel?) {
|
||||
guard let newMolecules = carouselModel?.molecules else {
|
||||
numberOfPages = 0
|
||||
@ -191,7 +197,7 @@ open class Carousel: View {
|
||||
pagingView = MoleculeObjectMapping.shared()?.createMolecule(molecule, delegateObject: delegateObject) as? (UIView & CarouselPageControlProtocol)
|
||||
}
|
||||
|
||||
addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20)))
|
||||
addPaging(view: pagingView, position: molecule?.position ?? 20)
|
||||
}
|
||||
|
||||
/// Registers the cells with the collection view
|
||||
@ -294,7 +300,7 @@ open class Carousel: View {
|
||||
|
||||
extension Carousel: UICollectionViewDelegateFlowLayout {
|
||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
let itemWidth = collectionView.bounds.width * itemWidthPercent
|
||||
return CGSize(width: itemWidth, height: collectionView.bounds.height)
|
||||
}
|
||||
|
||||
@ -324,8 +330,15 @@ extension Carousel: UICollectionViewDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
extension Carousel: UICollectionViewDelegate {
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
(collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol)?.didSelectCell(at: indexPath, delegateObject: delegateObject, additionalData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension Carousel: UIScrollViewDelegate {
|
||||
|
||||
/// Go to the cell at the specified index.
|
||||
func goTo(_ index: Int, animated: Bool) {
|
||||
|
||||
showPeaking(false)
|
||||
@ -339,51 +352,33 @@ extension Carousel: UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func handleUserOnBufferCell() {
|
||||
guard loop else { return }
|
||||
|
||||
let lastPageIndex = numberOfPages + 1
|
||||
let goToIndex = { (index: Int) in
|
||||
self.goTo(index, animated: false)
|
||||
self.collectionView.layoutIfNeeded()
|
||||
self.pagingView?.currentIndex = self.pageIndex
|
||||
}
|
||||
|
||||
if currentIndex < 2 {
|
||||
// If on a "buffer" last row (which is the first index), go to the real last row secretly. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking.
|
||||
goToIndex(lastPageIndex)
|
||||
} else if currentIndex > lastPageIndex {
|
||||
// If on the "buffer" first row (which is the index after the real last row), go to the real first row secretly.
|
||||
goToIndex(2)
|
||||
}
|
||||
}
|
||||
|
||||
func checkForDraggingOutOfBounds(_ scrollView: UIScrollView) {
|
||||
|
||||
guard loop, dragging else { return }
|
||||
|
||||
// Checks if the user is not paging but attempting to drag endlessly and goes out of bounds. Caps the index.
|
||||
if let separatorWidth = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing {
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
let index = scrollView.contentOffset.x / (itemWidth + separatorWidth)
|
||||
let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1
|
||||
|
||||
if index < 1 {
|
||||
currentIndex = 0
|
||||
updateModelIndex()
|
||||
} else if index > CGFloat(lastCellIndex - 1) {
|
||||
currentIndex = lastCellIndex
|
||||
updateModelIndex()
|
||||
/// Adjusts the current contentOffset if we are going onto buffer cells while looping to help with the endless scrolling appearance.
|
||||
func adjustOffsetForLooping(_ scrollView: UIScrollView) {
|
||||
let translatedPoint = scrollView.panGestureRecognizer.translation(in: scrollView.superview).x
|
||||
if translatedPoint > 0 {
|
||||
// Moving left, see if we are moving passed the first left buffer card and adjust
|
||||
if let threshold = collectionView.layoutAttributesForItem(at: IndexPath(item: 1, section: 0))?.frame.minX,
|
||||
scrollView.contentOffset.x < threshold,
|
||||
let newOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: numberOfPages + 1, section: 0))?.frame.minX {
|
||||
scrollView.contentOffset.x = newOffset
|
||||
}
|
||||
} else if translatedPoint < 0 {
|
||||
// Moving right, see if we are moving passed the first right buffer card and adjust
|
||||
if let threshold = collectionView.layoutAttributesForItem(at: IndexPath(item: numberOfPages + 2, section: 0))?.frame.maxX,
|
||||
scrollView.contentOffset.x + scrollView.bounds.width > threshold,
|
||||
let newEndOffset = collectionView.layoutAttributesForItem(at: IndexPath(item: 2, section: 0))?.frame.maxX {
|
||||
scrollView.contentOffset.x = newEndOffset - scrollView.bounds.width
|
||||
}
|
||||
}
|
||||
|
||||
handleUserOnBufferCell()
|
||||
}
|
||||
|
||||
open func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
|
||||
// Check if the user is dragging the card even further past the next card.
|
||||
//checkForDraggingOutOfBounds(scrollView)
|
||||
|
||||
// Adjust for looping
|
||||
if let model = model as? CarouselModel,
|
||||
model.loop == true {
|
||||
adjustOffsetForLooping(scrollView)
|
||||
}
|
||||
|
||||
// Let the pager know our progress if needed.
|
||||
pagingView?.scrollViewDidScroll(collectionView)
|
||||
@ -391,6 +386,7 @@ extension Carousel: UIScrollViewDelegate {
|
||||
|
||||
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
|
||||
// Disable peaking when dragging.
|
||||
dragging = true
|
||||
showPeaking(false)
|
||||
}
|
||||
@ -398,32 +394,63 @@ extension Carousel: UIScrollViewDelegate {
|
||||
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||||
|
||||
dragging = false
|
||||
targetContentOffset.pointee = scrollView.contentOffset
|
||||
|
||||
// This is for setting up smooth custom paging. (Since UICollectionView only handles paging based on collection view size and not cell size).
|
||||
guard let separatorWidth = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.minimumLineSpacing else { return }
|
||||
// This is for setting up smooth custom paging. (Since UICollectionView only handles paging based on collection view size and not cell size). Math requires that we are using UICollectionViewFlowLayout.
|
||||
guard (model as? CarouselModel)?.paging == true,
|
||||
let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
|
||||
|
||||
// We switch cards if we pass the velocity threshold or position threshold (currently 50%).
|
||||
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
|
||||
var cellToSwipeTo = Int(scrollView.contentOffset.x / (itemWidth + separatorWidth) + 0.5)
|
||||
let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1
|
||||
let velocityThreshold: CGFloat = 1.1
|
||||
let separatorWidth = layout.minimumLineSpacing
|
||||
let itemWidth = collectionView.bounds.width * itemWidthPercent
|
||||
let width = itemWidth + separatorWidth
|
||||
|
||||
if velocity.x > velocityThreshold {
|
||||
cellToSwipeTo = currentIndex + 1
|
||||
|
||||
} else if velocity.x < -velocityThreshold {
|
||||
cellToSwipeTo = currentIndex - 1
|
||||
// Adjusts the offset for the contentInset. Adds imaginary half separator to the left of the first card, which is necessary for determining the percent of a given card we are currently at.
|
||||
let adjustedOffset = scrollView.contentOffset.x - layout.sectionInset.left + (separatorWidth / 2)
|
||||
|
||||
// Calculates the offset per card depending on the alignment.
|
||||
var offsetByCard: CGFloat
|
||||
switch itemAlignment {
|
||||
case .right:
|
||||
offsetByCard = ((adjustedOffset + scrollView.bounds.width) / width) - 1
|
||||
case .centeredHorizontally:
|
||||
offsetByCard = ((adjustedOffset + (scrollView.bounds.width / 2)) / width) - 0.5
|
||||
default:
|
||||
offsetByCard = adjustedOffset / width
|
||||
}
|
||||
|
||||
// Adjust card for velocity impact.
|
||||
let velocityThreshold: CGFloat = 1.1
|
||||
var cellToSwipeTo: Int
|
||||
if velocity.x > velocityThreshold {
|
||||
cellToSwipeTo = Int(ceil(offsetByCard))
|
||||
} else if velocity.x < -velocityThreshold {
|
||||
cellToSwipeTo = Int(floor(offsetByCard))
|
||||
} else {
|
||||
cellToSwipeTo = Int(round(offsetByCard))
|
||||
}
|
||||
|
||||
// If we are swiping to a buffer cell, change to real cell before beginning animation so we don't go out of bounds.
|
||||
if cellToSwipeTo < 2 {
|
||||
let newOffset = scrollView.contentOffset.x + (width * CGFloat(numberOfPages))
|
||||
scrollView.contentOffset.x = newOffset
|
||||
targetContentOffset.pointee.x = newOffset
|
||||
cellToSwipeTo = cellToSwipeTo + numberOfPages
|
||||
} else if cellToSwipeTo > numberOfPages + 1 {
|
||||
let newOffset = scrollView.contentOffset.x - (width * CGFloat(numberOfPages))
|
||||
scrollView.contentOffset.x = newOffset
|
||||
targetContentOffset.pointee.x = newOffset
|
||||
cellToSwipeTo = cellToSwipeTo - numberOfPages
|
||||
} else {
|
||||
targetContentOffset.pointee = scrollView.contentOffset
|
||||
}
|
||||
|
||||
// Cap the index.
|
||||
let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1
|
||||
goTo(min(max(cellToSwipeTo, 0), lastCellIndex), animated: true)
|
||||
}
|
||||
|
||||
// To give the illusion of endless scrolling. Since we are always calling scrollToItem we can assume finished paging in here.
|
||||
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
|
||||
// Cycle to other end if on buffer cell.
|
||||
handleUserOnBufferCell()
|
||||
pagingView?.currentIndex = pageIndex
|
||||
showPeaking(true)
|
||||
}
|
||||
|
||||
@ -21,14 +21,18 @@ import UIKit
|
||||
public var backgroundColor: Color?
|
||||
public var molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]
|
||||
public var index: Int = 0
|
||||
public var spacing: Float?
|
||||
public var spacing: CGFloat?
|
||||
public var border: Bool?
|
||||
public var loop: Bool?
|
||||
public var height: Float?
|
||||
public var itemWidthPercent: Float?
|
||||
public var height: CGFloat?
|
||||
@Percent public var itemWidthPercent = 100
|
||||
public var itemAlignment: UICollectionView.ScrollPosition?
|
||||
public var pagingMolecule: (CarouselPagingModelProtocol & MoleculeModelProtocol)?
|
||||
|
||||
public var paging: Bool = true
|
||||
public var useHorizontalMargins: Bool?
|
||||
public var leftPadding: CGFloat?
|
||||
public var rightPadding: CGFloat?
|
||||
|
||||
public init(molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]) {
|
||||
self.molecules = molecules
|
||||
}
|
||||
@ -49,6 +53,10 @@ import UIKit
|
||||
case itemWidthPercent
|
||||
case itemAlignment
|
||||
case pagingMolecule
|
||||
case paging
|
||||
case useHorizontalMargins
|
||||
case leftPadding
|
||||
case rightPadding
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -60,13 +68,21 @@ import UIKit
|
||||
molecules = try typeContainer.decodeModels(codingKey: .molecules)
|
||||
index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
spacing = try typeContainer.decodeIfPresent(Float.self, forKey: .spacing)
|
||||
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
|
||||
border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
|
||||
loop = try typeContainer.decodeIfPresent(Bool.self, forKey: .loop)
|
||||
height = try typeContainer.decodeIfPresent(Float.self, forKey: .height)
|
||||
itemWidthPercent = try typeContainer.decodeIfPresent(Float.self, forKey: .itemWidthPercent)
|
||||
height = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .height)
|
||||
if let itemWidthPercent = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .itemWidthPercent) {
|
||||
self.itemWidthPercent = itemWidthPercent
|
||||
}
|
||||
itemAlignment = try typeContainer.decodeIfPresent(UICollectionView.ScrollPosition.self, forKey: .itemAlignment)
|
||||
pagingMolecule = try typeContainer.decodeModelIfPresent(codingKey: .pagingMolecule)
|
||||
if let paging = try typeContainer.decodeIfPresent(Bool.self, forKey: .paging) {
|
||||
self.paging = paging
|
||||
}
|
||||
useHorizontalMargins = try typeContainer.decodeIfPresent(Bool.self, forKey: .useHorizontalMargins)
|
||||
leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding)
|
||||
rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -74,12 +90,16 @@ import UIKit
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeModels(molecules, forKey: .molecules)
|
||||
try container.encode(spacing, forKey: .spacing)
|
||||
try container.encode(border, forKey: .border)
|
||||
try container.encode(loop, forKey: .loop)
|
||||
try container.encode(height, forKey: .height)
|
||||
try container.encodeIfPresent(spacing, forKey: .spacing)
|
||||
try container.encodeIfPresent(border, forKey: .border)
|
||||
try container.encodeIfPresent(loop, forKey: .loop)
|
||||
try container.encodeIfPresent(height, forKey: .height)
|
||||
try container.encode(itemWidthPercent, forKey: .itemWidthPercent)
|
||||
try container.encode(itemAlignment, forKey: .itemAlignment)
|
||||
try container.encodeIfPresent(itemAlignment, forKey: .itemAlignment)
|
||||
try container.encodeModelIfPresent(pagingMolecule, forKey: .pagingMolecule)
|
||||
try container.encode(paging, forKey: .paging)
|
||||
try container.encodeIfPresent(useHorizontalMargins, forKey: .useHorizontalMargins)
|
||||
try container.encodeIfPresent(leftPadding, forKey: .leftPadding)
|
||||
try container.encodeIfPresent(rightPadding, forKey: .rightPadding)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,5 +10,5 @@ import Foundation
|
||||
|
||||
|
||||
public protocol CarouselPagingModelProtocol {
|
||||
var position: Float? { get }
|
||||
var position: CGFloat? { get }
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ import Foundation
|
||||
return cell
|
||||
}
|
||||
|
||||
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
public override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
(collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol)?.didSelectCell(at: indexPath, delegateObject: delegateObjectIVar, additionalData: nil)
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
|
||||
/// A base collection view cell with basic mvm functionality.
|
||||
open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCoreViewProtocol, CollectionTemplateItemProtocol {
|
||||
open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCoreViewProtocol, CollectionTemplateItemProtocol, MFButtonProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -25,10 +25,6 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
// MARK: - Inits
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
@ -47,10 +43,6 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
// MARK: - MVMCoreViewProtocol
|
||||
open func setupView() {
|
||||
isAccessibilityElement = false
|
||||
@ -68,16 +60,6 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
|
||||
(molecule as? MVMCoreViewProtocol)?.updateView(size)
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
molecule?.reset()
|
||||
backgroundColor = .mvmWhite
|
||||
width = nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
// MARK: - MoleculeViewProtocol
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? CollectionItemModelProtocol else { return }
|
||||
@ -94,6 +76,12 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
|
||||
}
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
molecule?.reset()
|
||||
backgroundColor = .mvmWhite
|
||||
width = nil
|
||||
}
|
||||
|
||||
/// Convenience function. Adds a molecule to the view.
|
||||
open func addMolecule(_ molecule: MoleculeViewProtocol) {
|
||||
contentView.addSubview(molecule)
|
||||
@ -109,6 +97,12 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
|
||||
self.width = width
|
||||
}
|
||||
|
||||
// MARK: - Override
|
||||
public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
guard let action = model?.action else { return }
|
||||
Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
// Column logic, set width.
|
||||
override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
|
||||
let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
|
||||
|
||||
@ -9,5 +9,13 @@
|
||||
import Foundation
|
||||
|
||||
public protocol CollectionItemModelProtocol {
|
||||
|
||||
var action: ActionModelProtocol? { get set }
|
||||
}
|
||||
|
||||
// Not a strict requirement.
|
||||
public extension CollectionItemModelProtocol {
|
||||
var action: ActionModelProtocol? {
|
||||
get { return nil }
|
||||
set { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class TableViewCell: UITableViewCell, MoleculeViewProtocol, MoleculeListCellProtocol, MVMCoreViewProtocol {
|
||||
@objcMembers open class TableViewCell: UITableViewCell, MoleculeViewProtocol, MoleculeListCellProtocol, MVMCoreViewProtocol, MFButtonProtocol {
|
||||
|
||||
open var molecule: MoleculeViewProtocol?
|
||||
open var listItemModel: ListItemModelProtocol?
|
||||
@ -267,10 +267,8 @@ import UIKit
|
||||
}
|
||||
|
||||
public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
//TODO: Use object when handleAction is rewrote to handle action model
|
||||
if let actionMap = self.listItemModel?.action?.toJSON() {
|
||||
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
}
|
||||
guard let action = listItemModel?.action else { return }
|
||||
Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
public func willDisplay() {
|
||||
|
||||
@ -233,4 +233,8 @@ import Foundation
|
||||
}
|
||||
fatalError()
|
||||
}
|
||||
|
||||
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
(collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol)?.didSelectCell(at: indexPath, delegateObject: delegateObjectIVar, additionalData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user