From df34e1574c31ecc5770fab9fc30144b825bbaad4 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 18 Nov 2019 17:04:16 -0500 Subject: [PATCH 1/2] latest, updating. --- MVMCoreUI/Atoms/TextFields/DigitBox.swift | 83 ++++++++++++------- .../Atoms/TextFields/DigitEntryField.swift | 42 +++------- 2 files changed, 62 insertions(+), 63 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/DigitBox.swift b/MVMCoreUI/Atoms/TextFields/DigitBox.swift index 1c1776d8..c0b161b3 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitBox.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitBox.swift @@ -18,8 +18,11 @@ import UIKit // MARK: - Outlets //-------------------------------------------------- - let digitField: UITextField = { - let textField = UITextField(frame: .zero) + let digitField: TextField = { + let textField = TextField() + textField.isAccessibilityElement = true + textField.setContentCompressionResistancePriority(.required, for: .vertical) + textField.setContentCompressionResistancePriority(.required, for: .horizontal) textField.textAlignment = .center textField.keyboardType = .numberPad return textField @@ -31,6 +34,27 @@ import UIKit private var previousSize: CGFloat = 0.0 + //-------------------------------------------------- + // MARK: - Property Observer + //-------------------------------------------------- + + public override var showError: Bool { + didSet { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.borderStrokeColor = self.showError ? .mfPumpkin() : .mfSilver() + + let barHeight: CGFloat = self.showError ? 4 : 1 + self.bottomBar.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight) + self.bottomBar.backgroundColor = self.showError ? UIColor.mfPumpkin().cgColor : UIColor.black.cgColor + + self.setNeedsDisplay() + self.layoutIfNeeded() + } + } + } + //-------------------------------------------------- // MARK: - Delegate //-------------------------------------------------- @@ -59,7 +83,7 @@ import UIKit required public init?(coder: NSCoder) { super.init(coder: coder) - fatalError("DigitBox has not been implemented") + fatalError("DigitBox does not support xibs.") } //-------------------------------------------------- @@ -72,12 +96,19 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false backgroundColor = .white + + addSubview(digitField) digitField.delegate = self - showErrorState(false) + + NSLayoutConstraint.activate([ + digitField.heightAnchor.constraint(equalToConstant: 24), + digitField.topAnchor.constraint(equalTo: topAnchor, constant: 12), + digitField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12), + bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: 12), + trailingAnchor.constraint(equalTo: digitField.trailingAnchor, constant: 12)]) widthConstraint = widthAnchor.constraint(equalToConstant: 39) widthConstraint?.isActive = true - heightConstraint = heightAnchor.constraint(equalToConstant: 44) heightConstraint?.isActive = true @@ -96,14 +127,14 @@ import UIKit // MARK: - Methods //-------------------------------------------------- - public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - - if string.isBackspace { - textBoxDelegate?.textFieldDidDelete?(self.digitField) - } - - return true - } +// public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { +// +// if string.isBackspace { +// textBoxDelegate?.textFieldDidDelete?(self.digitField) +// } +// +// return true +// } public override func updateView(_ size: CGFloat) { super.updateView(size) @@ -140,26 +171,14 @@ import UIKit self.setNeedsLayout() } } - - func showErrorState(_ show: Bool) { - - showError = show - borderStrokeColor = show ? .mfPumpkin() : .mfSilver() - - let barHeight: CGFloat = show ? 4 : 1 - bottomBar.frame = CGRect(x: 0, y: bounds.height - barHeight, width: bounds.width, height: barHeight) - bottomBar.backgroundColor = show ? UIColor.mfPumpkin().cgColor : UIColor.black.cgColor - - setNeedsDisplay() - layoutIfNeeded() - } } // TODO: Move if working properly. -extension String { - var isBackspace: Bool { - let char = self.cString(using: String.Encoding.utf8)! - return strcmp(char, "\\b") == -92 - } -} +//extension String { +// +// var isBackspace: Bool { +// let char = self.cString(using: String.Encoding.utf8)! +// return strcmp(char, "\\b") == -92 +// } +//} diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index b352a89b..5fae6aa9 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -21,6 +21,10 @@ import UIKit public var digitFields: [DigitBox] = [] + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + //-------------------------------------------------- // MARK: - Property Observers //-------------------------------------------------- @@ -31,7 +35,6 @@ import UIKit digitFields.forEach { $0.isEnabled = self.isEnabled - $0.isUserInteractionEnabled = isEnabled $0.digitField.isEnabled = isEnabled $0.digitField.textColor = isEnabled ? .black : .mfBattleshipGrey() @@ -42,7 +45,6 @@ import UIKit public override var placeholder: String? { get { var string = "" - digitFields.forEach { string += $0.digitField.attributedPlaceholder?.string ?? "" } return !string.isEmpty ? string : nil @@ -58,7 +60,7 @@ import UIKit } } - // If there is already text in the textfield, set the place holder label below. + // If there is already text in the textfield, set the placeholder label below. if let text = text, !text.isEmpty && !showError { feedback = placeholder } else if !showError { @@ -78,7 +80,6 @@ import UIKit public override var text: String? { get { var string = "" - digitFields.forEach { string += $0.digitField.text ?? "" } return string @@ -109,9 +110,8 @@ import UIKit self.init(frame: .zero) } - public init(numberOfDigits: Int) { - super.init(frame: .zero) - + public convenience init(numberOfDigits: Int) { + self.init(frame: .zero) self.numberOfDigits = numberOfDigits } @@ -133,9 +133,10 @@ import UIKit alignCenterHorizontal() isAccessibilityElement = false + entryContainer.hideBorder = true entryContainer.bottomBar.backgroundColor = UIColor.clear.cgColor entryContainer.bottomBar.frame = CGRect(x: 0, y: entryContainer.bounds.height, width: 0, height: 0) - setupDigitFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth()) + assembleDigitFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth()) textField.removeFromSuperview() } @@ -149,7 +150,7 @@ import UIKit return digitBox } - func setupDigitFieldsView(size: CGFloat) { + func assembleDigitFieldsView(size: CGFloat) { var accessibleElements: [Any] = [titleLabel] @@ -166,7 +167,6 @@ import UIKit box.topAnchor.constraint(equalTo: entryContainer.topAnchor).isActive = true entryContainer.bottomAnchor.constraint(equalTo: box.bottomAnchor).isActive = true - box.centerYAnchor.constraint(equalTo: entryContainer.centerYAnchor).isActive = true if index == 0 { box.leadingAnchor.constraint(equalTo: entryContainer.leadingAnchor).isActive = true @@ -203,33 +203,13 @@ import UIKit self.digitFields.forEach { $0.updateView(size) } self.layoutIfNeeded() } - - // Layout text boxes. -// self.setupDigitFieldsView(size: size) } -// hideBorder = true } //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- - override func valueChanged() { - super.valueChanged() - - // TODO: is feedbackContainerDistance needed? -// DispatchQueue.main.async { [weak self] in -// guard let self = self else { return } -// -// if let feedback = self.feedback, !feedback.isEmpty { -// self.feedbackContainerDistance?.constant = 10 -// -// } else { -// self.feedbackContainerDistance?.constant = 0 -// } -// } - } - func setAsSecureTextEntry(_ secureEntry: Bool) { DispatchQueue.main.async { [weak self] in @@ -411,7 +391,7 @@ extension DigitEntryField { } } - setupDigitFieldsView(size: MVMCoreUIUtility.getWidth()) + assembleDigitFieldsView(size: MVMCoreUIUtility.getWidth()) } open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { From c38e3c07122946eb525358889221e4e4878555a3 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 19 Nov 2019 09:57:43 -0500 Subject: [PATCH 2/2] DigitEntry in decent place. --- .../Atoms/TextFields/DigitEntryField.swift | 78 +++++++++---------- MVMCoreUI/Containers/views/FormView.swift | 43 +++++----- 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 5fae6aa9..5e049d48 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -17,14 +17,10 @@ import UIKit //-------------------------------------------------- private(set) var numberOfDigits = 4 - private var switchedAutomatically = false + public var switchFieldsAutomatically = false public var digitFields: [DigitBox] = [] - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - //-------------------------------------------------- // MARK: - Property Observers //-------------------------------------------------- @@ -133,12 +129,10 @@ import UIKit alignCenterHorizontal() isAccessibilityElement = false - entryContainer.hideBorder = true + entryContainer.hideBorders = true entryContainer.bottomBar.backgroundColor = UIColor.clear.cgColor entryContainer.bottomBar.frame = CGRect(x: 0, y: entryContainer.bounds.height, width: 0, height: 0) assembleDigitFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth()) - - textField.removeFromSuperview() } private func createDigitField() -> DigitBox { @@ -155,7 +149,11 @@ import UIKit var accessibleElements: [Any] = [titleLabel] if numberOfDigits > 0 { - let digitFields = [DigitBox](repeating: createDigitField(), count: numberOfDigits) + var digitFields = [DigitBox]() + for _ in 0.. [AnyHashable]? { + open class func getEnabledDigitFields(_ textFieldToDetermine: [TextEntryField]) -> [AnyHashable]? { - var enabledTextFields = [AnyHashable]() - - for textfield in textFieldToDetermine ?? [] { - if textfield.isEnabled { - enabledTextFields.append(textfield) - } - } - - return enabledTextFields + return textFieldToDetermine.filter { $0.isEnabled } } } @@ -316,12 +312,12 @@ extension DigitEntryField { // One character, switch old value with new, select next textfield textField.text = string - selectNextTextField(textField, clear: false) + selectNextDigitField(textField, clear: false) valueChanged() return false } else if replacementLength == 0 && oldLength == 1 { - // non empty cell, clear and stay. + // Non empty cell, clear and stay. textField.text = "" valueChanged() return false @@ -336,12 +332,12 @@ extension DigitEntryField { func textFieldDidDelete(_ textField: UITextField?) { // Empty cell, go back to previous cell and clear. - selectPreviousTextField(textField, clear: true) + selectPreviousDigitField(textField, clear: true) } @objc public func textFieldDidBeginEditing(_ textField: UITextField) { - if !switchedAutomatically { + if !switchFieldsAutomatically { textField.text = "" valueChanged() } @@ -356,7 +352,7 @@ extension DigitEntryField { @objc public func textFieldShouldClear(_ textField: UITextField) -> Bool { - selectPreviousTextField(textField, clear: false) + selectPreviousDigitField(textField, clear: false) return uiTextFieldDelegate?.textFieldShouldClear?(textField) ?? true } @@ -374,7 +370,7 @@ extension DigitEntryField { // MARK: - Molecular extension DigitEntryField { - + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) @@ -385,16 +381,16 @@ extension DigitEntryField { numberOfDigits = digits } + assembleDigitFieldsView(size: MVMCoreUIUtility.getWidth()) + if !dictionary.isEmpty{ for digitBox in digitFields { MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) } } - - assembleDigitFieldsView(size: MVMCoreUIUtility.getWidth()) } open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return 44 + return 115 } } diff --git a/MVMCoreUI/Containers/views/FormView.swift b/MVMCoreUI/Containers/views/FormView.swift index 201bfb3d..44a5c4b5 100644 --- a/MVMCoreUI/Containers/views/FormView.swift +++ b/MVMCoreUI/Containers/views/FormView.swift @@ -24,7 +24,7 @@ import UIKit }() /// Determines if a border should be drawn. - public var hideBorder = false + public var hideBorders = false public var borderStrokeColor: UIColor = .mfSilver() private var borderPath: UIBezierPath = UIBezierPath() @@ -35,13 +35,17 @@ import UIKit public var showError = false { didSet { - showError ? errorUI() : originalUI() + if !hideBorders { + showError ? errorUI() : originalUI() + } } } public var isEnabled = true { didSet { - isEnabled ? originalUI() : disabledUI() + if !hideBorders { + isEnabled ? originalUI() : disabledUI() + } } } @@ -53,7 +57,9 @@ import UIKit public var isSelected = false { didSet { - isSelected ? selectedUI() : originalUI() + if !hideBorders { + isSelected ? selectedUI() : originalUI() + } } } @@ -86,7 +92,7 @@ import UIKit borderPath.removeAllPoints() - if !hideBorder { + if !hideBorders { // Brings the other half of the line inside the view to prevent cropping. let origin = bounds.origin let size = frame.size @@ -117,7 +123,7 @@ import UIKit open func originalUI() { isUserInteractionEnabled = true - hideBorder = false + hideBorders = false borderStrokeColor = .mfSilver() bottomBar.backgroundColor = UIColor.black.cgColor refreshUI(bottomBarSize: 1) @@ -126,7 +132,7 @@ import UIKit open func errorUI() { isUserInteractionEnabled = true - hideBorder = false + hideBorders = false borderStrokeColor = .mfPumpkin() bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor refreshUI(bottomBarSize: 4) @@ -135,7 +141,7 @@ import UIKit open func selectedUI() { isUserInteractionEnabled = true - hideBorder = false + hideBorders = false borderStrokeColor = .black bottomBar.backgroundColor = UIColor.black.cgColor refreshUI(bottomBarSize: 1) @@ -144,7 +150,7 @@ import UIKit open func lockedUI() { isUserInteractionEnabled = false - hideBorder = true + hideBorders = true borderStrokeColor = .clear bottomBar.backgroundColor = UIColor.clear.cgColor refreshUI(bottomBarSize: 1) @@ -154,19 +160,20 @@ import UIKit isUserInteractionEnabled = false borderStrokeColor = .mfSilver() - hideBorder = false bottomBar.backgroundColor = UIColor.mfSilver().cgColor refreshUI(bottomBarSize: 1) } open func refreshUI(bottomBarSize: CGFloat? = nil) { - let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) - bottomBar.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) - - delegateObject?.moleculeDelegate?.moleculeLayoutUpdated?(self) - setNeedsDisplay() - layoutIfNeeded() + if !hideBorders { + let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) + bottomBar.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) + + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated?(self) + setNeedsDisplay() + layoutIfNeeded() + } } //-------------------------------------------------- @@ -179,8 +186,8 @@ import UIKit guard let dictionary = json, !dictionary.isEmpty else { return } - if let hideBorder = dictionary["hideBorder"] as? Bool { - self.hideBorder = hideBorder + if let hideBorders = dictionary["hideBorders"] as? Bool { + self.hideBorders = hideBorders } } }