latest state

This commit is contained in:
Kevin G Christiano 2020-03-16 09:50:54 -04:00
parent ef5f864a02
commit 50920c83e0
9 changed files with 163 additions and 84 deletions

View File

@ -810,8 +810,8 @@
0A14F6B023E8C27A00EDF7F7 /* CarouselIndicator */ = {
isa = PBXGroup;
children = (
0A14F69223E349EF00EDF7F7 /* CarouselIndicator.swift */,
0A14F6A823E8750300EDF7F7 /* CarouselIndicatorModel.swift */,
0A14F69223E349EF00EDF7F7 /* CarouselIndicator.swift */,
0AAF8E29240EA57D008DD263 /* BarsCarouselIndicatorModel.swift */,
0A4253AE23F5C2C000554656 /* BarsIndicatorView.swift */,
0AAF8E2B240EA594008DD263 /* NumericCarouselIndicatorModel.swift */,

View File

@ -70,6 +70,9 @@ open class Arrow: View {
// MARK: - Drawing
//--------------------------------------------------
/**
Draws the arrow pointing to the right and then rotates the arrow x degrees counter-clockwise.
*/
open override func draw(_ rect: CGRect) {
super.draw(rect)

View File

@ -17,4 +17,33 @@ open class BarsCarouselIndicatorModel: CarouselIndicatorModel {
public class override var identifier: String {
return "barsCarouselIndicator"
}
public var currentIndicatorColor: Color = Color(uiColor: .mvmBlack)
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case currentIndicatorColor
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
public required init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
if let currentIndicatorColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentIndicatorColor) {
self.currentIndicatorColor = currentIndicatorColor
}
try super.init(from: decoder)
}
public override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(currentIndicatorColor, forKey: .currentIndicatorColor)
}
}

View File

@ -14,7 +14,7 @@ open class BarsIndicatorView: CarouselIndicator {
// MARK: - Stored Properties
//--------------------------------------------------
let stackView: StackView = {
public let stackView: StackView = {
let stackView = StackView()
stackView.axis = .horizontal
stackView.alignment = .bottom
@ -30,18 +30,49 @@ open class BarsIndicatorView: CarouselIndicator {
public static let indicatorBarWidth: CGFloat = 24
public static let indicatorBarHeight: (selected: CGFloat, unselected: CGFloat) = (selected: 4, unselected: 1)
/// Convenience to access the model.
public var barsCarouselIndicatorModel: BarsCarouselIndicatorModel? {
return model as? BarsCarouselIndicatorModel
}
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
open override var isEnabled: Bool {
didSet {
barReferences.forEach { view, heightConstraint in
view.backgroundColor = isEnabled ? indicatorTintColor : disabledIndicatorColor
barReferences.forEach { view, _ in
view.backgroundColor = isEnabled ? indicatorColor : disabledIndicatorColor
}
}
}
private(set) var _currentIndicatorColor: UIColor = .black
/// Colors the currently selected index, unique from other indicators
public var currentIndicatorColor: UIColor {
get { return _currentIndicatorColor }
set (newColor) {
_currentIndicatorColor = newColor
barsCarouselIndicatorModel?.currentIndicatorColor = Color(uiColor: newColor)
if !barReferences.isEmpty {
barReferences[currentIndex].view.backgroundColor = newColor
}
}
}
public override var indicatorColor: UIColor {
get { return _indicatorColor }
set (newColor) {
super.indicatorColor = newColor
for (i, barTuple) in barReferences.enumerated() where i != currentIndex {
barTuple.view.backgroundColor = newColor
}
}
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
@ -64,10 +95,15 @@ open class BarsIndicatorView: CarouselIndicator {
addSubview(stackView)
isUserInteractionEnabled = false
stackView.heightAnchor.constraint(equalToConstant: 4).isActive = true
stackView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
trailingAnchor.constraint(equalTo: stackView.trailingAnchor).isActive = true
NSLayoutConstraint.activate([
stackView.heightAnchor.constraint(equalToConstant: 4),
heightAnchor.constraint(equalTo: stackView.heightAnchor),
stackView.centerXAnchor.constraint(equalTo: centerXAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor),
bottomAnchor.constraint(equalTo: stackView.bottomAnchor),
trailingAnchor.constraint(equalTo: stackView.trailingAnchor)
])
}
//--------------------------------------------------
@ -81,7 +117,7 @@ open class BarsIndicatorView: CarouselIndicator {
for i in 0..<numberOfPages {
let bar = View()
bar.widthAnchor.constraint(equalToConstant: BarsIndicatorView.indicatorBarWidth).isActive = true
bar.backgroundColor = isEnabled ? indicatorTintColor : disabledIndicatorColor
bar.backgroundColor = isEnabled ? (i == currentIndex ? currentIndicatorColor : indicatorColor) : disabledIndicatorColor
let barHeight = i == currentIndex ? BarsIndicatorView.indicatorBarHeight.selected : BarsIndicatorView.indicatorBarHeight.unselected
let heightConstraint = bar.heightAnchor.constraint(equalToConstant: barHeight)
heightConstraint.isActive = true
@ -93,6 +129,19 @@ open class BarsIndicatorView: CarouselIndicator {
barReferences = bars
}
public override func assessTouchOf(_ touchPoint_X: CGFloat) {
currentIndex = barReferences.firstIndex { $0.0.frame.maxX >= touchPoint_X && $0.0.frame.minX <= touchPoint_X } ?? 0
}
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? BarsCarouselIndicatorModel else { return }
currentIndicatorColor = model.currentIndicatorColor.uiColor
}
//--------------------------------------------------
// MARK: - IndicatorViewProtocol
//--------------------------------------------------
@ -111,7 +160,7 @@ open class BarsIndicatorView: CarouselIndicator {
}
let expression = {
self.barReferences[previousIndex].view.backgroundColor = self.indicatorTintColor
self.barReferences[previousIndex].view.backgroundColor = self.indicatorColor
self.barReferences[newIndex].view.backgroundColor = self.currentIndicatorColor
self.barReferences[previousIndex].constraint.constant = BarsIndicatorView.indicatorBarHeight.unselected
self.barReferences[newIndex].constraint.constant = BarsIndicatorView.indicatorBarHeight.selected

View File

@ -48,11 +48,13 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
public var currentIndex: Int {
get { return _currentIndex }
set (newIndex) {
carouselIndicatorModel?.currentIndex = newIndex
previousIndex = _currentIndex
_currentIndex = newIndex
performAction()
updateUI(previousIndex: previousIndex, newIndex: newIndex, totalCount: numberOfPages, isAnimated: carouselIndicatorModel?.isAnimated ?? true)
if previousIndex != newIndex {
updateUI(previousIndex: previousIndex, newIndex: newIndex, totalCount: numberOfPages, isAnimated: carouselIndicatorModel?.isAnimated ?? true)
}
}
}
@ -64,6 +66,7 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
get { return _numberOfPages }
set (newTotal) {
guard _numberOfPages != newTotal else { return }
carouselIndicatorModel?.numberOfPages = newTotal
_numberOfPages = newTotal
isHidden = carouselIndicatorModel?.hidesForSinglePage ?? false && newTotal <= 1
@ -75,33 +78,12 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
return carouselIndicatorModel?.disabledIndicatorColor.uiColor ?? .mvmCoolGray3
}
public var indicatorTintColor: UIColor {
get { return carouselIndicatorModel?.indicatorColor.uiColor ?? .black }
private(set) var _indicatorColor: UIColor = .black
public var indicatorColor: UIColor {
get { return _indicatorColor }
set (newColor) {
carouselIndicatorModel?.indicatorColor = Color(uiColor: newColor)
// if isBarIndicator(), let barIndicator = indicatorView as? BarsIndicatorView {
// for (i, barTuple) in barIndicator.barReferences.enumerated() where i != currentIndex {
// barTuple.view.backgroundColor = newColor
// }
// }
}
}
private var _currentIndicatorColor: UIColor = .black
/// Colors the currently selected index, unique from other indicators
public var currentIndicatorColor: UIColor {
get { return _currentIndicatorColor }
set (newColor) {
_currentIndicatorColor = newColor
carouselIndicatorModel?.currentIndicatorColor = Color(uiColor: newColor)
// if isBarIndicator() {
// if let barIndicator = indicatorView as? BarsIndicatorView, !barIndicator.barReferences.isEmpty {
// barIndicator.barReferences[currentIndex].view.backgroundColor = newColor
// }
// }
}
}
@ -184,19 +166,11 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
let touchPoint = tapGesture?.location(in: self)
let touchPoint_X = touchPoint?.x ?? 0.0
// if isBarIndicator(), let bars = (indicatorView as? BarsIndicatorView)?.barReferences {
// currentIndex = bars.firstIndex { $0.0.frame.maxX >= touchPoint_X && $0.0.frame.minX <= touchPoint_X } ?? 0
//
// } else {
// // Determine which half of the view was touched.
// if touchPoint_X > bounds.width / 2 {
// incrementCurrentIndex()
// } else {
// decrementCurrentIndex()
// }
// }
assessTouchOf(touchPoint_X)
}
func assessTouchOf(_ touchPoint_X: CGFloat) { }
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
@ -215,15 +189,13 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
open override func set(with model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? CarouselIndicatorModel else { return }
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
// indicatorType = IndicatorType(rawValue: model.type) ?? .hybrid
currentIndicatorColor = model.currentIndicatorColor.uiColor
indicatorTintColor = model.indicatorColor.uiColor
guard let model = model as? CarouselIndicatorModel else { return }
indicatorColor = model.indicatorColor.uiColor
currentIndex = model.currentIndex
isEnabled = model.isEnabled
if let accessibleValue = MVMCoreUIUtility.hardcodedString(withKey: model.accessibilityHasSlidesInsteadOfPage ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") {

View File

@ -22,8 +22,10 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
public var moleculeName: String?
/// The maxmum count of pages before the indicatorView forces a Numeric Indicator in place of Bar.
public var numberOfPages: Int = 0
// Sets the current Index to focus on.
public var currentIndex: Int = 0
public var isAnimated: Bool = true
public var hidesForSinglePage: Bool = false
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
@ -31,8 +33,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
public var isEnabled: Bool = true
public var disabledIndicatorColor: Color = Color(uiColor: .mvmCoolGray3)
public var indicatorColor: Color = Color(uiColor: .mvmBlack)
public var currentIndicatorColor: Color = Color(uiColor: .mvmBlack)
public var padding: Float?
public var position: Float?
/// Allows sendActions() to trigger even if index is already at min/max index.
public var alwaysSendAction = false
@ -44,7 +45,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case type
case currentIndex
case numberOfPages
case alwaysSendAction
case isAnimated
@ -54,7 +55,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
case disabledIndicatorColor
case indicatorColor
case currentIndicatorColor
case padding
case position
}
//--------------------------------------------------
@ -70,12 +71,16 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
self.numberOfPages = numberOfPages
}
if let currentIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .currentIndex) {
self.currentIndex = currentIndex
}
if let alwaysSendAction = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysSendAction) {
self.alwaysSendAction = alwaysSendAction
}
if let padding = try typeContainer.decodeIfPresent(Float.self, forKey: .padding) {
self.padding = padding
if let position = try typeContainer.decodeIfPresent(Float.self, forKey: .position) {
self.position = position
}
if let isAnimated = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAnimated) {
@ -101,25 +106,21 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol {
if let indicatorColor = try typeContainer.decodeIfPresent(Color.self, forKey: .indicatorColor) {
self.indicatorColor = indicatorColor
}
if let currentIndicatorColor = try typeContainer.decodeIfPresent(Color.self, forKey: .currentIndicatorColor) {
self.currentIndicatorColor = currentIndicatorColor
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(numberOfPages, forKey: .numberOfPages)
try container.encodeIfPresent(alwaysSendAction, forKey: .alwaysSendAction)
try container.encodeIfPresent(isAnimated, forKey: .isAnimated)
try container.encode(numberOfPages, forKey: .numberOfPages)
try container.encode(currentIndex, forKey: .currentIndex)
try container.encode(alwaysSendAction, forKey: .alwaysSendAction)
try container.encode(isAnimated, forKey: .isAnimated)
try container.encodeIfPresent(hidesForSinglePage, forKey: .hidesForSinglePage)
try container.encodeIfPresent(accessibilityHasSlidesInsteadOfPage, forKey: .accessibilityHasSlidesInsteadOfPage)
try container.encodeIfPresent(isEnabled, forKey: .isEnabled)
try container.encodeIfPresent(disabledIndicatorColor, forKey: .disabledIndicatorColor)
try container.encodeIfPresent(indicatorColor, forKey: .indicatorColor)
try container.encodeIfPresent(currentIndicatorColor, forKey: .currentIndicatorColor)
try container.encodeIfPresent(padding, forKey: .padding)
try container.encode(isEnabled, forKey: .isEnabled)
try container.encode(disabledIndicatorColor, forKey: .disabledIndicatorColor)
try container.encode(indicatorColor, forKey: .indicatorColor)
try container.encodeIfPresent(position, forKey: .position)
}
}

View File

@ -40,9 +40,23 @@ open class NumericIndicatorView: CarouselIndicator {
open override var isEnabled: Bool {
didSet {
pageCount.textColor = isEnabled ? indicatorTintColor : disabledIndicatorColor
leftArrow.tintColor = isEnabled ? indicatorTintColor : disabledIndicatorColor
rightArrow.tintColor = isEnabled ? indicatorTintColor : disabledIndicatorColor
pageCount.textColor = isEnabled ? indicatorColor : disabledIndicatorColor
leftArrow.tintColor = isEnabled ? indicatorColor : disabledIndicatorColor
rightArrow.tintColor = isEnabled ? indicatorColor : disabledIndicatorColor
}
}
/// Sets the color for pageCount text, left arrow and right arrow.
public override var indicatorColor: UIColor {
get { return _indicatorColor }
set (newColor) {
super.indicatorColor = newColor
if isEnabled {
pageCount.textColor = newColor
leftArrow.tintColor = newColor
rightArrow.tintColor = newColor
}
}
}
@ -96,6 +110,15 @@ open class NumericIndicatorView: CarouselIndicator {
])
}
public override func assessTouchOf(_ touchPoint_X: CGFloat) {
if touchPoint_X > bounds.width / 2 {
incrementCurrentIndex()
} else {
decrementCurrentIndex()
}
}
//--------------------------------------------------
// MARK: - IndicatorViewProtocol
//--------------------------------------------------

View File

@ -10,5 +10,5 @@ import Foundation
public protocol CarouselPagingModelProtocol: MoleculeModelProtocol {
var padding: Float? { get }
var position: Float? { get }
}

View File

@ -176,7 +176,7 @@ open class Carousel: View {
pagingView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(molecule, delegateObject, false) as? (UIView & CarouselPageControlProtocol)
}
addPaging(view: pagingView, padding: (CGFloat(molecule?.padding ?? 20)))
addPaging(view: pagingView, position: (CGFloat(molecule?.position ?? 20)))
}
/// Registers the cells with the collection view
@ -221,7 +221,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 & CarouselPageControlProtocol)?, padding: CGFloat) {
open func addPaging(view: (UIView & CarouselPageControlProtocol)?, position: CGFloat) {
pagingView?.removeFromSuperview()
bottomPin?.isActive = false
@ -234,13 +234,15 @@ open class Carousel: View {
addSubview(pagingView)
pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: padding).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true
bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true
bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor)
bottomPin?.priority = .defaultLow
bottomPin?.isActive = true
pagingView.numberOfPages = numberOfPages
(pagingView as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(.fill)
pageIndex = pagingView.currentIndex
pagingView.indicatorTouchAction = { [weak self] pager in
DispatchQueue.main.async {
guard let self = self else { return }