From af54ac2a3cc10c76583438c7936c8bc77a0609d8 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 31 Jan 2020 15:38:07 -0500 Subject: [PATCH] getting ready for an evolution --- MVMCoreUI/Atoms/Views/PageControl.swift | 57 ++++++++++++------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/PageControl.swift b/MVMCoreUI/Atoms/Views/PageControl.swift index 2f3dada4..cac93fef 100644 --- a/MVMCoreUI/Atoms/Views/PageControl.swift +++ b/MVMCoreUI/Atoms/Views/PageControl.swift @@ -8,16 +8,11 @@ import Foundation -public protocol PagingIndicatorProtocol: class { - typealias PagingTouchBlock = (PagingIndicatorProtocol) -> () - var currentPage: Int { get } - var numberOfPages: Int { get } - // func setPagingTouchBlock(_ pagingTouchBlock: PagingTouchBlock?) - // func scrollViewDidScroll(_ collectionView: UICollectionView) -} - - -open class PageControl: Control, PagingIndicatorProtocol { +/** + This class is implemented to focus primarily on the page control logic. + Visual flourishes and bespoke behavior should be subclassed from here. + */ +open class PageControl: Control { //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- @@ -38,18 +33,19 @@ open class PageControl: Control, PagingIndicatorProtocol { public var indicatorType: IndicatorType = .hybrid public var indicatorSpacing: CGFloat { - get { return containerStack.spacing } + get { return stackView.spacing } set { - containerStack.spacing = newValue - containerStack.layoutIfNeeded() + stackView.spacing = newValue + stackView.layoutIfNeeded() } } + public let indicatorBarWidth: CGFloat = 24 public let indicatorBarHeight: (selected: CGFloat, unselected: CGFloat) = (selected: 4, unselected: 1) private(set) var indicators = [BarIndicator]() - var containerStack: StackView = { + var stackView: StackView = { let stack = StackView() stack.axis = .horizontal stack.distribution = .equalSpacing @@ -57,11 +53,13 @@ open class PageControl: Control, PagingIndicatorProtocol { return stack }() - public var pagingTouchBlock: PagingIndicatorProtocol.PagingTouchBlock? + public var pagingTouchBlock: ((Int)->())? // a flag to allow to send UIControlEventValueChanged actions all the time // e.g. going to previous element at first place and going to next at last place // While current rectangle won't change, need update current page + // When awlaysSenfingControlEvent is false, and user is already at first or final index, if user try to increment or decrement, won't do action + // while self.awlaysSenfingControlEven is YES, it still send control event, while the rectangle won't change, need set currentPage again. public var alwaysSendingControlEvent = false /// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false @@ -69,6 +67,9 @@ open class PageControl: Control, PagingIndicatorProtocol { public var isAnimated = false public var hidesForSinglePage = false + /// If true, then index will wraparound, otherwise it will stop paging at min/max index. + public var allowIndexWraparound = false + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -165,21 +166,21 @@ open class PageControl: Control, PagingIndicatorProtocol { open override func setupView() { super.setupView() - if containerStack.subviews.isEmpty { + if stackView.subviews.isEmpty { if let accessibleValue = MVMCoreUIUtility.hardcodedString(withKey: isSlidesAccessibile ? "MVMCoreUIPageControlslides_currentpage_index" : "MVMCoreUIPageControl_currentpage_index") { accessibilityValue = String(format: accessibleValue, currentPage + 1, numberOfPages) } - addSubview(containerStack) - containerStack.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true - containerStack.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor).isActive = true - trailingAnchor.constraint(lessThanOrEqualTo: containerStack.trailingAnchor).isActive = true + addSubview(stackView) + stackView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true + stackView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor).isActive = true + trailingAnchor.constraint(lessThanOrEqualTo: stackView.trailingAnchor).isActive = true - topConstraint = containerStack.topAnchor.constraint(equalTo: topAnchor, constant: PaddingThree) + topConstraint = stackView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingThree) topConstraint?.priority = .defaultHigh topConstraint?.isActive = true - bottomConstraint = bottomAnchor.constraint(equalTo: containerStack.bottomAnchor, constant: PaddingThree) + bottomConstraint = bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: PaddingThree) bottomConstraint?.priority = .defaultHigh bottomConstraint?.isActive = true @@ -231,7 +232,7 @@ open class PageControl: Control, PagingIndicatorProtocol { func indicatorTapped(_ tapGesture: UITapGestureRecognizer?) { if isUserInteractionEnabled { - let touchPoint_X = tapGesture?.location(in: containerStack).x ?? 0.0 + let touchPoint_X = tapGesture?.location(in: stackView).x ?? 0.0 let index = indicators.firstIndex { indicator in return indicator.frame.maxX >= touchPoint_X && indicator.frame.minX <= touchPoint_X @@ -240,7 +241,7 @@ open class PageControl: Control, PagingIndicatorProtocol { if let selectIndex = index { currentPage = selectIndex sendActions(for: .valueChanged) - pagingTouchBlock?(self) + pagingTouchBlock?(selectIndex) } } } @@ -287,21 +288,19 @@ open class PageControl: Control, PagingIndicatorProtocol { accessibilityAdjust(toPage: currentPage - 1) } - // When awlaysSenfingControlEvent is false, and user is already at first or final index, if user try to increment or decrement, won't do action - // while self.awlaysSenfingControlEven is YES, it still send control event, while the rectangle won't change, need set currentPage again. func accessibilityAdjust(toPage index: Int) { if (index < numberOfPages && index >= 0) || alwaysSendingControlEvent { isAnimated = false currentPage = index sendActions(for: .valueChanged) - pagingTouchBlock?(self) + pagingTouchBlock?(index) } } func setTopBottomSpace(constant: CGFloat) { - self.bottomConstraint?.constant = constant - self.topConstraint?.constant = constant + bottomConstraint?.constant = constant + topConstraint?.constant = constant } public class BarIndicator: View {