adding new base class. improving carousel logic.

This commit is contained in:
Kevin G Christiano 2020-02-13 15:33:55 -05:00
parent 6ede310cd0
commit 5558cc8324
8 changed files with 291 additions and 75 deletions

View File

@ -85,6 +85,7 @@
0A4253AF23F5C2C100554656 /* BarsIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A4253AE23F5C2C000554656 /* BarsIndicatorView.swift */; };
0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */; };
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; };
0A7918F523F5E7EA00772FF4 /* ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7918F423F5E7EA00772FF4 /* ImageView.swift */; };
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; };
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
@ -412,6 +413,7 @@
0A4253AE23F5C2C000554656 /* BarsIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarsIndicatorView.swift; sourceTree = "<group>"; };
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = "<group>"; };
0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryField.swift; sourceTree = "<group>"; };
0A7918F423F5E7EA00772FF4 /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = "<group>"; };
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
0A7BAFA2232BE63400FB8E22 /* CheckboxLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxLabel.swift; sourceTree = "<group>"; };
@ -1471,6 +1473,7 @@
D2755D7A23689C7500485468 /* TableViewCell.swift */,
0A5D59C323AD488600EFD9E9 /* Protocols */,
0A14F6A423E4803A00EDF7F7 /* StackView.swift */,
0A7918F423F5E7EA00772FF4 /* ImageView.swift */,
);
path = BaseClasses;
sourceTree = "<group>";
@ -1819,6 +1822,7 @@
01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */,
D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */,
D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */,
0A7918F523F5E7EA00772FF4 /* ImageView.swift in Sources */,
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
D243859923A16B1800332775 /* Container.swift in Sources */,
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */,

View File

@ -8,14 +8,24 @@
import Foundation
/// Set protocols for all indicator faces of the Carousel Indicator.
public protocol IndicatorViewProtocol {
func updateUI(previousIndex: Int, newIndex: Int, totalCount: Int, isAnimated: Bool)
func reset()
var isEnabled: Bool { get set }
}
/// Contracts behavior between carousel and its page control.
public protocol CarouselPageControlProtocol {
typealias PagingTouchBlock = ((CarouselPageControlProtocol)) -> ()
var currentIndex: Int { get set }
var numberOfPages: Int { get set }
var indicatorTouchAction: PagingTouchBlock? { get set }
func scrollViewDidScroll(_ collectionView: UICollectionView)
}
open class CarouselIndicator: Control {
open class CarouselIndicator: Control, CarouselPageControlProtocol {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
@ -45,9 +55,12 @@ open class CarouselIndicator: Control {
didSet { assignIndicatorView() }
}
public var uiGestures: Set<UIGestureRecognizer> = []
/// The currently active indicator view.
public var currentIndicator: IndicatorView?
/// Convenience to access the model.
public var carouselIndicatorModel: CarouselIndicatorModel? {
return model as? CarouselIndicatorModel
}
@ -65,14 +78,15 @@ open class CarouselIndicator: Control {
}
}
/// The maxmum count of pages before the indicatorView forces a numeric Indicator insead of Bar.
/// The maxmum count of pages before the indicatorView forces a Numeric Indicator in place of Bar.
public var hybridThreshold: Int = 5
/// Set this closure to perform an action when a different indicator was selected.
public var indicatorTouchAction: ((Int)->())?
/// Passes through oldInde and newIndex, respectively.
public var indicatorTouchAction: CarouselIndicator.PagingTouchBlock?
/// Allows sendActions() to trigger even if index is min/max index.
public var alwaysSendEvent = false
/// Allows sendActions() to trigger even if index is already at min/max index.
public var alwaysSendAction = false
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
public var accessibilityHasSlidesInsteadOfPage = false
@ -91,17 +105,9 @@ open class CarouselIndicator: Control {
didSet {
isUserInteractionEnabled = isEnabled
indicatorView?.isEnabled = isEnabled
if indicatorType != .bar && numberOfPages > hybridThreshold {
} else {
if let stackView = indicatorView as? BarsIndicatorView {
stackView.stackView.arrangedSubviews.forEach { ($0 as? BarsIndicatorView)?.isEnabled = isEnabled }
}
}
}
}
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
@ -112,21 +118,21 @@ open class CarouselIndicator: Control {
public var currentIndex: Int {
get { return _currentIndex }
set (newIndex) {
guard _currentIndex != newIndex else { return }
if !allowIndexWraparound {
guard _currentIndex != newIndex else { return }
}
previousIndex = _currentIndex
_currentIndex = newIndex
sendActions(for: .valueChanged)
indicatorTouchAction?(newIndex)
indicatorView?.updateUI(previousIndex: previousIndex,
newIndex: newIndex,
totalCount: numberOfPages,
isAnimated: isAnimated)
performAction()
updateUI()
}
}
private var _numberOfPages = 0
/// Holds the total number of pages displayed by the carousel.
/// Updating this property will potentially update the UI.
public var numberOfPages: Int {
get { return _numberOfPages }
set (newTotal) {
@ -140,14 +146,7 @@ open class CarouselIndicator: Control {
indicatorView = BarsIndicatorView()
}
if alwaysSendEvent {
sendActions(for: .valueChanged)
}
indicatorView?.updateUI(previousIndex: previousIndex,
newIndex: currentIndex,
totalCount: newTotal,
isAnimated: isAnimated)
updateUI()
}
}
@ -159,6 +158,12 @@ open class CarouselIndicator: Control {
get { return _indicatorTintColor }
set (newColor) {
_indicatorTintColor = newColor
if isBarIndicator(), let barIndicator = indicatorView as? BarsIndicatorView {
for (i, barTuple) in barIndicator.barsReference.enumerated() where i != currentIndex {
barTuple.view.backgroundColor = newColor
}
}
}
}
@ -169,6 +174,12 @@ open class CarouselIndicator: Control {
get { return _currentIndicatorColor }
set (newColor) {
_currentIndicatorColor = newColor
if isBarIndicator() {
if let barIndicator = indicatorView as? BarsIndicatorView {
barIndicator.barsReference[currentIndex].view.backgroundColor = newColor
}
}
}
}
@ -207,9 +218,8 @@ open class CarouselIndicator: Control {
open override func setupView() {
super.setupView()
guard indicatorView == nil else { return }
assignIndicatorView()
setupGestures()
if let accessibleValue = MVMCoreUIUtility.hardcodedString(withKey: accessibilityHasSlidesInsteadOfPage ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") {
accessibilityValue = String(format: accessibleValue, currentIndex + 1, numberOfPages)
@ -220,22 +230,49 @@ open class CarouselIndicator: Control {
// MARK: - UITouch
//--------------------------------------------------
@objc func pageValueIncrement() {
private func setupGestures() {
let tap = UITapGestureRecognizer(target: self, action: #selector(indicatorTapped(_:)))
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeLeft))
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeRight))
uiGestures.insert(tap)
uiGestures.insert(leftSwipe)
uiGestures.insert(rightSwipe)
}
func incrementCurrentIndex() {
currentIndex = min(currentIndex + 1, numberOfPages - 1)
}
@objc func pageValueDecrement() {
func decrementCurrentIndex() {
currentIndex = max(0, currentIndex - 1)
}
func indicatorTapped(_ tapGesture: UITapGestureRecognizer?) {
/// Increments the currentIndex value.
@objc func swipeLeft() {
incrementCurrentIndex()
}
/// Decrement the currentIndex value
@objc func swipeRight() {
decrementCurrentIndex()
}
/// Handles tap logic for Indicator
@objc func indicatorTapped(_ tapGesture: UITapGestureRecognizer?) {
if isEnabled, let bars = (indicatorView as? BarsIndicatorView)?.barsReference {
let touchPoint_X = tapGesture?.location(in: self).x ?? 0.0
let touchPoint = tapGesture?.location(in: self)
let touchPoint_X = touchPoint?.x ?? 0.0
if isEnabled, indicatorType == .bar, let bars = (indicatorView as? BarsIndicatorView)?.barsReference {
currentIndex = bars.firstIndex { $0.0.frame.maxX >= touchPoint_X && $0.0.frame.minX <= touchPoint_X } ?? 0
} else {
if touchPoint_X > bounds.width / 2 {
incrementCurrentIndex()
} else {
decrementCurrentIndex()
}
}
}
@ -243,6 +280,20 @@ open class CarouselIndicator: Control {
// MARK: - Methods
//--------------------------------------------------
public func updateUI() {
indicatorView?.updateUI(previousIndex: previousIndex,
newIndex: currentIndex,
totalCount: numberOfPages,
isAnimated: isAnimated)
}
public func performAction() {
sendActions(for: .valueChanged)
indicatorTouchAction?(self)
}
/// Sets the indicatorView based on the current indicatorType.
func assignIndicatorView() {
@ -260,9 +311,13 @@ open class CarouselIndicator: Control {
/// Convenience to determine if current view is displaying bars.
func isBarIndicator() -> Bool {
return indicatorType != .bar && numberOfPages > hybridThreshold
}
public func scrollViewDidScroll(_ collectionView: UICollectionView) {
}
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
@ -284,20 +339,22 @@ open class CarouselIndicator: Control {
//--------------------------------------------------
open override func accessibilityIncrement() {
accessibilityAdjust(toPage: currentIndex + 1)
}
open override func accessibilityDecrement() {
accessibilityAdjust(toPage: currentIndex - 1)
}
func accessibilityAdjust(toPage index: Int) {
if (index < numberOfPages && index >= 0) || alwaysSendEvent {
if (index < numberOfPages && index >= 0) || alwaysSendAction {
isAnimated = false
previousIndex = currentIndex
currentIndex = index
sendActions(for: .valueChanged)
indicatorTouchAction?(index)
performAction()
}
}

View File

@ -54,7 +54,6 @@ public class CarouselIndicatorModel: MoleculeModelProtocol {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
currentBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentBarColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
barsColor = try typeContainer.decodeIfPresent(Color.self, forKey: .barsColor)

View File

@ -77,8 +77,6 @@ open class BarsIndicatorView: View, IndicatorViewProtocol {
open override func setupView() {
super.setupView()
guard subviews.isEmpty else { return }
addSubview(stackView)
isUserInteractionEnabled = false

View File

@ -11,7 +11,7 @@ import UIKit
open class NumericIndicatorView: View, IndicatorViewProtocol {
//--------------------------------------------------
// MARK: - Properties
// MARK: - Outlets
//--------------------------------------------------
/// Text to display the current count of total pages for viewing.
@ -22,7 +22,41 @@ open class NumericIndicatorView: View, IndicatorViewProtocol {
return label
}()
open var isEnabled: Bool = true
let leftArrow: ImageView = {
let arrow = UIImage(named: "peakingRightArrow")?.withRenderingMode(.alwaysTemplate).withHorizontallyFlippedOrientation()
let imageView = ImageView(image: arrow)
imageView.isUserInteractionEnabled = true
imageView.tintColor = .mvmBlack
return imageView
}()
let rightArrow: ImageView = {
let arrow = UIImage(named: "peakingRightArrow")?.withRenderingMode(.alwaysTemplate)
let imageView = ImageView(image: arrow)
imageView.isUserInteractionEnabled = true
imageView.tintColor = .mvmBlack
return imageView
}()
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var isEnabled: Bool = true {
didSet {
titleLabel.isEnabled = isEnabled
leftArrow.tintColor = isEnabled ? enabledColor : disabledColor
rightArrow.tintColor = isEnabled ? enabledColor : disabledColor
}
}
public var enabledColor: UIColor {
return (superview as? CarouselIndicator)?.indicatorTintColor ?? .black
}
public var disabledColor: UIColor {
return (superview as? CarouselIndicator)?.disabledIndicatorColor ?? .mvmCoolGray3
}
public var parentCarouselIndicator: CarouselIndicator? {
return superview as? CarouselIndicator
@ -74,23 +108,18 @@ open class NumericIndicatorView: View, IndicatorViewProtocol {
open override func setupView() {
super.setupView()
guard subviews.isEmpty else { return }
isUserInteractionEnabled = false
leftArrow.tintColor = isEnabled ? enabledColor : disabledColor
rightArrow.tintColor = isEnabled ? enabledColor : disabledColor
addSubview(titleLabel)
titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
NSLayoutConstraint.constraintPinSubview(titleLabel, pinTop: true, pinBottom: true, pinLeft: false, pinRight: false)
let arrow = UIImage(named: "peakingRightArrow")?.withHorizontallyFlippedOrientation()
let leftArrow = UIImageView(image: arrow)
leftArrow.isUserInteractionEnabled = true
addSubview(leftArrow)
NSLayoutConstraint.constraintPinView(leftArrow, heightConstraint: true, heightConstant: PaddingTwo, widthConstraint: true, widthConstant: PaddingTwo)
leftArrow.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
let rightArrow = UIImageView(image: UIImage(named: "peakingRightArrow"))
addSubview(rightArrow)
NSLayoutConstraint.constraintPinView(rightArrow, heightConstraint: true, heightConstant: PaddingTwo, widthConstraint: true, widthConstant: PaddingTwo)

View File

@ -0,0 +1,102 @@
//
// ImageView.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 2/13/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import UIKit
class ImageView: UIImageView, ModelMoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var json: [AnyHashable: Any]?
open var model: MoleculeModelProtocol?
private var initialSetupPerformed = false
//--------------------------------------------------
// MARK: - Initialization
//--------------------------------------------------
public override init(frame: CGRect) {
super.init(frame: .zero)
initialSetup()
}
override init(image: UIImage?) {
super.init(image: image)
initialSetup()
}
public convenience init() {
self.init(frame: .zero)
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
public func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
setupView()
}
}
// MARK:- ModelMoleculeViewProtocol
open func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
self.model = model
if let backgroundColor = model?.backgroundColor {
self.backgroundColor = backgroundColor.uiColor
}
}
open class func nameForReuse(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
return model?.moleculeName
}
open class func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return nil
}
open class func requiredModules(_ molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> [String]? {
return nil
}
}
// MARK:- MVMCoreViewProtocol
extension ImageView: MVMCoreViewProtocol {
open func updateView(_ size: CGFloat) {}
/// Will be called only once.
open func setupView() {
translatesAutoresizingMaskIntoConstraints = false
insetsLayoutMarginsFromSafeArea = false
MVMCoreUIUtility.setMarginsFor(self, leading: 0, top: 0, trailing: 0, bottom: 0)
}
}
// MARK:- MVMCoreUIMoleculeViewProtocol
extension ImageView: MVMCoreUIMoleculeViewProtocol {
open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
self.json = json
if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) {
backgroundColor = UIColor.mfGet(forHex: backgroundColorString)
}
}
open func reset() {
backgroundColor = .clear
}
open func setAsMolecule() { }
}

View File

@ -9,6 +9,10 @@
import UIKit
@objcMembers open class View: UIView, ModelMoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
open var json: [AnyHashable: Any]?
open var model: MoleculeModelProtocol?

View File

@ -9,6 +9,9 @@
import UIKit
open class Carousel: View {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
@ -45,13 +48,15 @@ open class Carousel: View {
var loop = false
private var dragging = false
// For adding pager
/// For adding pager
private var bottomPin: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - MVMCoreViewProtocol
//--------------------------------------------------
open override func setupView() {
super.setupView()
guard collectionView.superview == nil else { return }
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.dataSource = self
@ -68,6 +73,7 @@ open class Carousel: View {
open override func updateView(_ size: CGFloat) {
super.updateView(size)
collectionView.collectionViewLayout.invalidateLayout()
showPeaking(false)
@ -79,7 +85,9 @@ open class Carousel: View {
}
}
//--------------------------------------------------
// MARK: - MVMCoreUIMoleculeViewProtocol
//--------------------------------------------------
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
@ -106,10 +114,13 @@ open class Carousel: View {
collectionView.reloadData()
}
//--------------------------------------------------
// MARK: - JSON Setters
/// Updates the layout being used
//--------------------------------------------------
/// Updates the layout being used
func setupLayout(with carouselModel: CarouselModel?) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = CGFloat(carouselModel?.spacing ?? 1)
@ -126,6 +137,7 @@ open class Carousel: View {
numberOfPages = newMolecules.count
molecules = newMolecules
if carouselModel?.loop ?? false && newMolecules.count > 2 {
// Sets up the row data with buffer cells on each side (for illusion of endless scroll... also has one more buffer cell on each side in case we can peek that cell).
loop = true
@ -134,6 +146,7 @@ open class Carousel: View {
molecules?.append(newMolecules.first!)
molecules?.append(newMolecules[1])
}
pageIndex = 0
}
@ -144,6 +157,7 @@ open class Carousel: View {
if let molecule = molecule {
pagingView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(molecule, delegateObject, false) as? (UIView & MVMCoreUIPagingProtocol)
}
addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20)))
}
@ -156,7 +170,10 @@ open class Carousel: View {
}
}
//--------------------------------------------------
// MARK: - Convenience
//--------------------------------------------------
/// Returns the (identifier, class) of the molecule for the given map.
func getMoleculeInfo(with molecule: MoleculeModelProtocol, delegateObject: MVMCoreUIDelegateObject?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? {
guard let className = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(molecule),
@ -182,6 +199,7 @@ open class Carousel: View {
/// Adds a paging view. Centers it horizontally with the collection view. The position is the vertical distance from the center of the page view to the bottom of the collection view.
open func addPaging(view: (UIView & MVMCoreUIPagingProtocol)?, position: CGFloat) {
pagingView?.removeFromSuperview()
guard let pagingView = view else {
bottomPin?.isActive = false
@ -189,6 +207,7 @@ open class Carousel: View {
bottomPin?.isActive = true
return
}
pagingView.translatesAutoresizingMaskIntoConstraints = false
addSubview(pagingView)
pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
@ -201,15 +220,13 @@ open class Carousel: View {
pagingView.setNumberOfPages(numberOfPages)
(pagingView as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(.fill)
pagingView.setPagingTouch { [weak self] (pager) in
MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let localSelf = self else {
return
}
pagingView.setPagingTouch { [weak self] pager in
DispatchQueue.main.async {
guard let self = self else { return }
let currentPage = pager.currentPage()
localSelf.pageIndex = currentPage
localSelf.goTo(localSelf.currentIndex, animated: !UIAccessibility.isVoiceOverRunning)
})
self.pageIndex = currentPage
self.goTo(self.currentIndex, animated: !UIAccessibility.isVoiceOverRunning)
}
}
self.pagingView = pagingView
}
@ -246,7 +263,7 @@ open class Carousel: View {
array?.append(pagingView!)
}
self.accessibilityElements = array
accessibilityElements = array
} else {
cell.accessibilityElementsHidden = true
}
@ -254,6 +271,7 @@ open class Carousel: View {
}
extension Carousel: UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
return CGSize(width: itemWidth, height: collectionView.bounds.height)
@ -265,6 +283,7 @@ extension Carousel: UICollectionViewDelegateFlowLayout {
}
extension Carousel: UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return molecules?.count ?? 0
}
@ -280,6 +299,7 @@ extension Carousel: UICollectionViewDataSource {
protocolCell.setWithModel(moleculeInfo.molecule, nil, nil)
protocolCell.updateView(collectionView.bounds.width)
}
setAccessiblity(cell, index: indexPath.row)
return cell
}
@ -290,20 +310,22 @@ extension Carousel: UIScrollViewDelegate {
func goTo(_ index: Int, animated: Bool) {
showPeaking(false)
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)), index: index)
self.currentIndex = index
self.collectionView.scrollToItem(at: IndexPath(row: self.currentIndex, section: 0), at: self.itemAlignment, animated: animated)
if let cell = collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)) {
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: self.currentIndex, section: 0)), index: index)
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), index: index)
currentIndex = index
collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: animated)
if let cell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) {
setAccessiblity(collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), index: index)
UIAccessibility.post(notification: .layoutChanged, argument: cell)
}
}
func handleUserOnBufferCell() {
guard loop else { return }
let lastPageIndex = numberOfPages + 1
let goToIndex = {(index: Int) in
let goToIndex = { (index: Int) in
self.goTo(index, animated: false)
self.collectionView.layoutIfNeeded()
self.pagingView?.setPage(self.pageIndex)
@ -319,6 +341,7 @@ extension Carousel: UIScrollViewDelegate {
}
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.
@ -326,10 +349,12 @@ extension Carousel: UIScrollViewDelegate {
let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent)
let index = scrollView.contentOffset.x / (itemWidth + separatorWidth)
let lastCellIndex = collectionView(collectionView, numberOfItemsInSection: 0) - 1
if index < 1 {
self.currentIndex = 0
currentIndex = 0
} else if index > CGFloat(lastCellIndex - 1) {
self.currentIndex = lastCellIndex
currentIndex = lastCellIndex
}
}
@ -379,9 +404,7 @@ extension Carousel: UIScrollViewDelegate {
public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
// Cycle to other end if on buffer cell.
handleUserOnBufferCell()
pagingView?.setPage(pageIndex)
showPeaking(true)
}
}