This commit is contained in:
Kevin G Christiano 2019-11-06 09:12:18 -05:00
parent 88eec2bf9d
commit 6d7c1df7cc
5 changed files with 121 additions and 124 deletions

View File

@ -28,10 +28,10 @@ import UIKit
private var previousSize: CGFloat = 0.0 private var previousSize: CGFloat = 0.0
/// Determines if a border should be drawn. /// Determines if a border should be drawn.
private var hideBorder = false var hideBorder = false
private var showError = false var showError = false
private var borderStrokeColor: UIColor = .mfSilver() var borderStrokeColor: UIColor = .mfSilver()
private var borderPath: UIBezierPath = UIBezierPath() private var borderPath: UIBezierPath = UIBezierPath()
//-------------------------------------------------- //--------------------------------------------------

View File

@ -10,40 +10,35 @@ import UIKit
/** /**
* Subclass of TextEntryField due to the conveniences provided. * Subclass of TextEntryField due to the conveniences provided.
* TODO: Compare overrides to determine if TextEntryField is necessary.
*/ */
@objcMembers open class DigitEntryField: TextEntryField, DigitBoxDelegate { @objcMembers open class DigitEntryField: TextEntryField, DigitBoxDelegate {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Outlets // MARK: - Outlets
//-------------------------------------------------- //--------------------------------------------------
public private(set) var digitFieldsView: UIView? public private(set) var digitFieldsStack: UIStackView?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
private var numberOfDigits = 4 private(set) var numberOfDigits = 4
private var switchedAutomatically = false private var switchedAutomatically = false
public var digitFields: [DigitBox] = [] public var digitFields: [DigitBox] = []
public override var isEnabled: Bool { public override var isEnabled: Bool {
didSet { didSet {
if isEnabled { titleLabel.textColor = isEnabled ? .black : .black
titleLabel.textColor = .black
} else {
titleLabel.textColor = .mfBattleshipGrey()
}
for textField in digitFields { for digitBox in digitFields {
textField.isUserInteractionEnabled = isEnabled digitBox.isUserInteractionEnabled = isEnabled
textField.isEnabled = isEnabled digitBox.isEnabled = isEnabled
textField.textColor = isEnabled ? .black : .mfBattleshipGrey() digitBox.textColor = isEnabled ? .black : .mfBattleshipGrey()
} }
} }
} }
/// Sets placeholder text in the textField.
public override var placeholder: String? { public override var placeholder: String? {
get { get {
var string = "" var string = ""
@ -85,6 +80,7 @@ import UIKit
} }
} }
/// Traverses each digitbox to retrieve the held value.
public override var text: String? { public override var text: String? {
get { get {
var string = "" var string = ""
@ -107,34 +103,48 @@ import UIKit
} }
} }
public override var title: String? { /// Updates the visual appearance of the container, with some logical laterations as well.
get { return titleLabel.text } public override func updateUI(appearance: Appearance) {
set {
if let formText = newValue, !formText.isEmpty { self.appearance = appearance
titleContainerDistance?.constant = 10 isUserInteractionEnabled = true
} else { titleLabel.textColor = .mfBattleshipGrey()
titleContainerDistance?.constant = 0 hideBorder = false
feedback = showError ? errorMessage : nil
switch appearance {
case .original:
digitFields.forEach {
$0.borderStrokeColor = .mfSilver()
$0.bottomBar.backgroundColor = UIColor.black.cgColor
} }
case .error:
super.title = newValue digitFields.forEach {
} $0.borderStrokeColor = .mfPumpkin()
} $0.bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor
public override var errorMessage: String? {
didSet {
if let errorMessage = errorMessage, !errorMessage.isEmpty {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
if self.showError {
self.feedbackContainerDistance?.constant = 10
self.setNeedsLayout()
}
self.digitFields.forEach { $0.showErrorState(true) }
}
} }
self.digitFields.forEach { $0.showErrorState(true) }
case .lock:
digitFields.forEach {
$0.isUserInteractionEnabled = false
$0.hideBorder = true
$0.bottomBar.backgroundColor = UIColor.clear.cgColor
}
case .select:
digitFields.forEach {
$0.borderStrokeColor = .black
$0.bottomBar.backgroundColor = UIColor.black.cgColor
}
case .disable:
digitFields.forEach {
$0.isUserInteractionEnabled = false
$0.borderStrokeColor = .mfSilver()
$0.bottomBar.backgroundColor = self.isEnabled ? UIColor.black.cgColor : UIColor.mfSilver().cgColor
}
titleLabel.textColor = self.isEnabled ? .mfBattleshipGrey() : .mfSilver()
} }
refreshBorderUI(bottomBarSize: appearance == .error ? 4 : 1)
} }
//-------------------------------------------------- //--------------------------------------------------
@ -158,7 +168,7 @@ import UIKit
} }
public init(numberOfDigits: Int, bothDelegates delegate: (UITextFieldDelegate & TextFieldDelegate)?, size: CGFloat? = nil) { public init(numberOfDigits: Int, bothDelegates delegate: (UITextFieldDelegate & TextFieldDelegate)?, size: CGFloat? = nil) {
super.init(bothDelegates: delegate as? (TextFieldDelegate & UITextFieldDelegate)) super.init(bothDelegates: delegate)
setup() setup()
self.numberOfDigits = numberOfDigits self.numberOfDigits = numberOfDigits
@ -176,52 +186,18 @@ import UIKit
open func setup() { open func setup() {
// Border for Field Container will not be shown.
hideBorder = true hideBorder = true
// titleLabel.styleB2(true)
alignCenterHorizontal() alignCenterHorizontal()
isAccessibilityElement = false
} }
open override func setupFieldContainerContent(_ container: UIView) { open override func setupFieldContainerContent(_ container: UIView) {
textField.removeFromSuperview()
setupTextFieldsView(forSize: CGFloat(numberOfDigits)) setupTextFieldsView(forSize: CGFloat(numberOfDigits))
} }
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.titleLabel.updateView(size)
if !self.digitFields.isEmpty {
StackableViewController.remove(self.digitFields)
self.digitFields.forEach { $0.updateView(size) }
}
// Layout text boxes.
self.setupTextFieldsView(forSize: size)
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
func removeError() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.digitFields.forEach { $0.showErrorState(false) }
}
}
func createDigitField() -> DigitBox { func createDigitField() -> DigitBox {
let textField = DigitBox() let textField = DigitBox()
@ -237,7 +213,7 @@ import UIKit
// Remove all current UI. // Remove all current UI.
if !digitFields.isEmpty { if !digitFields.isEmpty {
StackableViewController.remove(digitFields) digitFieldsStack?.subviews.forEach { $0.removeFromSuperview() }
} }
if numberOfDigits > 0 { if numberOfDigits > 0 {
@ -258,6 +234,42 @@ import UIKit
accessibilityElements = accessibleElements + [feedbackLabel] accessibilityElements = accessibleElements + [feedbackLabel]
} }
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open override func updateView(_ size: CGFloat) {
super.updateView(size)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.titleLabel.updateView(size)
if !self.digitFields.isEmpty {
self.digitFieldsStack?.subviews.forEach { $0.removeFromSuperview() }
self.digitFields.forEach { $0.updateView(size) }
}
// Layout text boxes.
self.setupTextFieldsView(forSize: size)
}
}
//--------------------------------------------------
// MARK: - Methods
//--------------------------------------------------
func removeError() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.digitFields.forEach { $0.showErrorState(false) }
}
}
override func valueChanged() { override func valueChanged() {
super.valueChanged() super.valueChanged()
@ -289,27 +301,13 @@ import UIKit
func setupTextFieldsView(forSize size: CGFloat) { func setupTextFieldsView(forSize size: CGFloat) {
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize(), guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
let digitFieldsView = digitFieldsView
else { return }
StackableViewController.populateViewHorizontally(digitFieldsView, withUIArray: digitFields, withSpacingBlock: { object in let stack = UIStackView(arrangedSubviews: digitFields)
self.digitFieldsStack = stack
var inset = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space) textField.addSubview(stack)
stack.distribution = .equalSpacing
if self.digitFields.count == 1 { stack.spacing = space
inset.left = 0
inset.right = 0
} else if let field = object as? UITextField, field == self.digitFields.first {
inset.left = 0
} else if let field = object as? UITextField, field == self.digitFields.last {
inset.right = 0
}
return inset
})
} }
public override func defaultValidationBlock() { public override func defaultValidationBlock() {
@ -367,6 +365,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
guard let dictionary = json else { return } guard let dictionary = json else { return }
@ -382,25 +381,12 @@ import UIKit
} }
buildTextFieldsView(size: MVMCoreUIUtility.getWidth()) buildTextFieldsView(size: MVMCoreUIUtility.getWidth())
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
} }
open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 44 return 44
} }
//--------------------------------------------------
// MARK: - Accessibility
//--------------------------------------------------
open override class func accessibilityElements() -> [Any]? {
// let fields = []
// return self.digitFields
return nil
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Text Field Delegate // MARK: - Text Field Delegate
//-------------------------------------------------- //--------------------------------------------------

View File

@ -73,7 +73,7 @@ import UIKit
return layer return layer
}() }()
public private(set) var appearance: Appearance = .original public var appearance: Appearance = .original
public var showError = false public var showError = false

View File

@ -160,6 +160,7 @@
strokeColor = .black strokeColor = .black
} }
/// Ensure you have defined a CaretSize with Orientation before calling.
@objc public func setConstraints() { @objc public func setConstraints() {
guard let dimensions = size?.dimensions() else { return } guard let dimensions = size?.dimensions() else { return }

View File

@ -23,6 +23,7 @@ import UIKit
// For separation between cells. // For separation between cells.
public var topSeparatorView: SeparatorView? public var topSeparatorView: SeparatorView?
public var bottomSeparatorView: SeparatorView? public var bottomSeparatorView: SeparatorView?
public enum SeparatorFrequency: String { public enum SeparatorFrequency: String {
case all case all
case allExceptTop case allExceptTop
@ -40,17 +41,21 @@ import UIKit
// MARK: - Styling // MARK: - Styling
open func style(with styleString: String?) { open func style(with styleString: String?) {
guard let styleString = styleString else {
return guard let styleString = styleString else { return }
}
switch styleString { switch styleString {
case "standard": case "standard":
styleStandard() styleStandard()
case "header": case "header":
styleHeader() styleHeader()
case "none": case "none":
styleNone() styleNone()
default: break
default:
break
} }
} }
@ -204,13 +209,18 @@ import UIKit
// MARK: - Arrow // MARK: - Arrow
/// Adds the standard mvm style caret to the accessory view /// Adds the standard mvm style caret to the accessory view
@objc public func addCaretViewAccessory() { @objc public func addCaretViewAccessory() {
guard accessoryView == nil else { return } guard accessoryView == nil else { return }
let width: CGFloat = 6
let height: CGFloat = 10
caretView = CaretView(lineWidth: 1) caretView = CaretView(lineWidth: 1)
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height) caretView?.size = .small(.vertical)
caretViewWidthSizeObject = MFSizeObject(standardSize: width, standardiPadPortraitSize: 9) caretView?.setConstraints()
caretViewHeightSizeObject = MFSizeObject(standardSize: height, standardiPadPortraitSize: 16)
if let size = caretView?.size?.dimensions() {
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
}
accessoryView = caretView accessoryView = caretView
} }
@ -258,7 +268,7 @@ import UIKit
} else { } else {
topSeparatorView?.hide() topSeparatorView?.hide()
bottomSeparatorView?.setAsLight() bottomSeparatorView?.setAsLight()
setSeparatorFrequency(TableViewCell.SeparatorFrequency.allExceptTop, indexPath: indexPath) setSeparatorFrequency(.allExceptTop, indexPath: indexPath)
} }
} }