Latest changes to make it better.

This commit is contained in:
Kevin G Christiano 2019-12-18 16:12:09 -05:00
parent d8030b178f
commit 37ddf23278
6 changed files with 116 additions and 132 deletions

View File

@ -24,6 +24,7 @@ import UIKit
textField.setContentCompressionResistancePriority(.required, for: .vertical) textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.setContentCompressionResistancePriority(.required, for: .horizontal) textField.setContentCompressionResistancePriority(.required, for: .horizontal)
textField.textAlignment = .center textField.textAlignment = .center
textField.font = MFStyler.fontForTextField()
textField.keyboardType = .numberPad textField.keyboardType = .numberPad
return textField return textField
}() }()
@ -72,6 +73,7 @@ import UIKit
private weak var widthConstraint: NSLayoutConstraint? private weak var widthConstraint: NSLayoutConstraint?
private weak var heightConstraint: NSLayoutConstraint? private weak var heightConstraint: NSLayoutConstraint?
private weak var digitFieldHeight: NSLayoutConstraint?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -106,12 +108,14 @@ import UIKit
digitField.delegate = self digitField.delegate = self
digitField.didDeleteDelegate = self digitField.didDeleteDelegate = self
digitFieldHeight = digitField.heightAnchor.constraint(equalToConstant: 24)
digitFieldHeight?.isActive = true
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
digitField.heightAnchor.constraint(equalToConstant: 24), digitField.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne),
digitField.topAnchor.constraint(greaterThanOrEqualTo: topAnchor), digitField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: PaddingOne),
digitField.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor), bottomAnchor.constraint(equalTo: digitField.bottomAnchor, constant: PaddingOne),
bottomAnchor.constraint(greaterThanOrEqualTo: digitField.bottomAnchor), trailingAnchor.constraint(equalTo: digitField.trailingAnchor, constant: PaddingOne),
trailingAnchor.constraint(greaterThanOrEqualTo: digitField.trailingAnchor),
digitField.centerYAnchor.constraint(equalTo: centerYAnchor), digitField.centerYAnchor.constraint(equalTo: centerYAnchor),
digitField.centerXAnchor.constraint(equalTo: centerXAnchor)]) digitField.centerXAnchor.constraint(equalTo: centerXAnchor)])
@ -145,7 +149,8 @@ import UIKit
@objc open override func reset() { @objc open override func reset() {
super.reset() super.reset()
digitField.text = nil backgroundColor = .clear
digitField.font = MFStyler.fontForTextField()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -161,28 +166,31 @@ import UIKit
super.updateView(size) super.updateView(size)
if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(previousSize)) { if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(previousSize)) {
MFStyler.styleTextField(digitField)
digitField.font = MFFonts.mfFont55Rg(28)
var width: CGFloat = 0 var width: CGFloat = 0
var height: CGFloat = 0 var height: CGFloat = 0
var pointSize: CGFloat = 13
let sizeObject = MFSizeObject(standardBlock: { let sizeObject = MFSizeObject(standardBlock: {
width = 39 width = 39
height = 44 height = 44
pointSize = 16
}, smalliPhone: { }, smalliPhone: {
width = 35 width = 35
height = 38 height = 38
pointSize = 13
}, standardiPadPortraitBlock: { }, standardiPadPortraitBlock: {
width = 59 width = 59
height = 74 height = 74
pointSize = 32
}) })
sizeObject?.performBlockBase(onSize: size) sizeObject?.performBlockBase(onSize: size)
widthConstraint?.constant = width widthConstraint?.constant = width
heightConstraint?.constant = height heightConstraint?.constant = height
digitField.font = MFFonts.mfFont55Rg(pointSize)
previousSize = size previousSize = size
} }

View File

@ -16,7 +16,53 @@ import UIKit
// MARK: - Stored Properties // MARK: - Stored Properties
//-------------------------------------------------- //--------------------------------------------------
private(set) var numberOfDigits = 4 private(set) var numberOfDigits = 4 {
didSet {
guard entryFieldContainer.subviews.isEmpty || oldValue != numberOfDigits else { return }
var accessibleElements: [Any] = [titleLabel]
if numberOfDigits > 0 {
var digitBoxes = [DigitBox]()
for _ in 0..<numberOfDigits {
digitBoxes.append(createDigitField())
}
self.digitBoxes = digitBoxes
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
var prevBox: DigitBox?
for (index, box) in digitBoxes.enumerated() {
accessibleElements.append(box)
entryFieldContainer.addSubview(box)
box.topAnchor.constraint(equalTo: entryFieldContainer.topAnchor).isActive = true
entryFieldContainer.bottomAnchor.constraint(equalTo: box.bottomAnchor).isActive = true
if index == 0 {
box.leadingAnchor.constraint(equalTo: entryFieldContainer.leadingAnchor).isActive = true
} else if index == digitBoxes.count - 1 {
if let prevTrailingAnchor = prevBox?.trailingAnchor {
box.leadingAnchor.constraint(equalTo: prevTrailingAnchor, constant: space).isActive = true
}
entryFieldContainer.trailingAnchor.constraint(greaterThanOrEqualTo: box.trailingAnchor).isActive = true
} else {
if let prevTrailingAnchor = prevBox?.trailingAnchor {
box.leadingAnchor.constraint(equalTo: prevTrailingAnchor, constant: space).isActive = true
}
}
prevBox = box
}
}
accessibilityElements = accessibleElements + [feedbackLabel]
}
}
/// Monitors if fields are being selected internally. /// Monitors if fields are being selected internally.
private var switchFieldsAutomatically = false private var switchFieldsAutomatically = false
@ -130,7 +176,6 @@ import UIKit
@objc public convenience init(numberOfDigits: Int, secureDigits: Bool = false) { @objc public convenience init(numberOfDigits: Int, secureDigits: Bool = false) {
self.init(frame: .zero) self.init(frame: .zero)
self.numberOfDigits = numberOfDigits self.numberOfDigits = numberOfDigits
assembleDigitFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth())
if secureDigits { if secureDigits {
setAsSecureTextEntry(true) setAsSecureTextEntry(true)
@ -162,49 +207,6 @@ import UIKit
return digitBox return digitBox
} }
@objc func assembleDigitFieldsView(size: CGFloat) {
var accessibleElements: [Any] = [titleLabel]
resetDigitBoxes()
if numberOfDigits > 0 {
var digitBoxes = [DigitBox]()
for _ in 0..<numberOfDigits {
digitBoxes.append(createDigitField())
}
self.digitBoxes = digitBoxes
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
var prevBox: DigitBox?
for (index, box) in digitBoxes.enumerated() {
accessibleElements.append(box)
entryFieldContainer.addSubview(box)
box.topAnchor.constraint(equalTo: entryFieldContainer.topAnchor).isActive = true
entryFieldContainer.bottomAnchor.constraint(equalTo: box.bottomAnchor).isActive = true
if index == 0 {
box.leadingAnchor.constraint(equalTo: entryFieldContainer.leadingAnchor).isActive = true
} else if index == digitBoxes.count - 1 {
box.leadingAnchor.constraint(equalTo: prevBox!.trailingAnchor, constant: space).isActive = true
entryFieldContainer.trailingAnchor.constraint(greaterThanOrEqualTo: box.trailingAnchor).isActive = true
} else {
box.leadingAnchor.constraint(equalTo: prevBox!.trailingAnchor, constant: space).isActive = true
}
prevBox = box
}
}
accessibilityElements = accessibleElements + [feedbackLabel]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -218,40 +220,23 @@ import UIKit
guard let self = self else { return } guard let self = self else { return }
if !self.digitBoxes.isEmpty { if !self.digitBoxes.isEmpty {
self.digitBoxes.forEach { $0.updateView(size) } self.digitBoxes.forEach { $0.updateView(size) }
self.layoutIfNeeded() self.layoutIfNeeded()
} }
} }
} }
@objc open override func reset() {
super.reset()
resetDigitBoxes()
}
func resetDigitBoxes() {
digitBoxes.forEach { $0.reset() }
digitBoxes = []
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods
//-------------------------------------------------- //--------------------------------------------------
@objc public func setAsSecureTextEntry(_ secureEntry: Bool) { @objc public func setAsSecureTextEntry(_ secureEntry: Bool) {
DispatchQueue.main.async { [weak self] in for (index, field) in self.digitBoxes.enumerated() {
guard let self = self else { return } field.digitField.isSecureTextEntry = secureEntry
for (index, field) in self.digitBoxes.enumerated() { // Accessibility - 33704 fix voice over will read what pin user is filling
field.digitField.isSecureTextEntry = secureEntry field.accessibilityLabel = String(format: "PIN %lu of %lu", UInt(index) + 1, UInt(self.digitBoxes.count))
// Accessibility - 33704 fix voice over will read what pin user is filling
field.accessibilityLabel = String(format: "PIN %lu of %lu", UInt(index) + 1, UInt(self.digitBoxes.count))
}
} }
} }
@ -263,7 +248,7 @@ import UIKit
return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count return enteredValue.count > 0 && enteredValue.count == self.digitBoxes.count
} }
} }
@objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) { @objc public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectPreviousField = false var selectPreviousField = false
@ -310,6 +295,10 @@ import UIKit
} }
} }
//--------------------------------------------------
// MARK: - Observing TextField Changes
//--------------------------------------------------
@objc override func startEditing() { @objc override func startEditing() {
selectedDigitBox?.isSelected = true selectedDigitBox?.isSelected = true
@ -442,12 +431,7 @@ extension DigitEntryField {
guard let dictionary = json else { return } guard let dictionary = json else { return }
let digits = dictionary["digits"] as? Int ?? 4 numberOfDigits = dictionary["digits"] as? Int ?? 4
if digits != numberOfDigits {
numberOfDigits = digits
}
assembleDigitFieldsView(size: MVMCoreUIUtility.getWidth())
if let _ = dictionary["secureEntry"] as? Bool { if let _ = dictionary["secureEntry"] as? Bool {
setAsSecureTextEntry(true) setAsSecureTextEntry(true)

View File

@ -28,6 +28,7 @@ import UIKit
public private(set) var entryFieldContainer = EntryFieldContainer() public private(set) var entryFieldContainer = EntryFieldContainer()
/// Provides contextual information on the TextField.
public private(set) var feedbackLabel: Label = { public private(set) var feedbackLabel: Label = {
let label = Label() let label = Label()
label.font = MFStyler.fontForTextFieldUnderLabel() label.font = MFStyler.fontForTextFieldUnderLabel()
@ -50,7 +51,13 @@ import UIKit
public var fieldKey: String? public var fieldKey: String?
public var errorMessage: String? public var errorMessage: String?
public var standardMessage: String? public var standardMessage: String? {
didSet {
if !showError {
feedback = standardMessage
}
}
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Computed Properties // MARK: - Computed Properties
@ -60,12 +67,8 @@ import UIKit
public var isEnabled: Bool { public var isEnabled: Bool {
get { return entryFieldContainer.isEnabled } get { return entryFieldContainer.isEnabled }
set (enabled) { set (enabled) {
DispatchQueue.main.async { [weak self] in self.feedbackLabel.textColor = enabled ? .black : .mfSilver()
guard let self = self else { return } self.entryFieldContainer.isEnabled = enabled
self.entryFieldContainer.isEnabled = enabled
self.feedbackLabel.textColor = enabled ? .black : .mfSilver()
}
} }
} }
@ -73,12 +76,8 @@ import UIKit
public var showError: Bool { public var showError: Bool {
get { return entryFieldContainer.showError } get { return entryFieldContainer.showError }
set (error) { set (error) {
DispatchQueue.main.async { [weak self] in self.feedback = error ? self.errorMessage : self.standardMessage
guard let self = self else { return } self.entryFieldContainer.showError = error
self.entryFieldContainer.showError = error
self.feedback = error ? self.errorMessage : self.standardMessage
}
} }
} }
@ -86,11 +85,7 @@ import UIKit
public var isLocked: Bool { public var isLocked: Bool {
get { return entryFieldContainer.isLocked } get { return entryFieldContainer.isLocked }
set (locked) { set (locked) {
DispatchQueue.main.async { [weak self] in self.entryFieldContainer.isLocked = locked
guard let self = self else { return }
self.entryFieldContainer.isLocked = locked
}
} }
} }
@ -98,11 +93,7 @@ import UIKit
public var isSelected: Bool { public var isSelected: Bool {
get { return entryFieldContainer.isSelected } get { return entryFieldContainer.isSelected }
set (selected) { set (selected) {
DispatchQueue.main.async { [weak self] in self.entryFieldContainer.isSelected = selected
guard let self = self else { return }
self.entryFieldContainer.isSelected = selected
}
} }
} }
@ -126,7 +117,12 @@ import UIKit
get { return feedbackLabel.text } get { return feedbackLabel.text }
set (newFeedback) { set (newFeedback) {
feedbackLabel.text = newFeedback feedbackLabel.text = newFeedback
entryFieldContainer.refreshUI()
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.entryFieldContainer.refreshUI()
}
} }
} }
@ -194,6 +190,7 @@ import UIKit
titleLabelLeading?.isActive = true titleLabelLeading?.isActive = true
addSubview(entryFieldContainer) addSubview(entryFieldContainer)
entryFieldContainer.setContentCompressionResistancePriority(.required, for: .vertical)
setupFieldContainerContent(entryFieldContainer) setupFieldContainerContent(entryFieldContainer)
titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4) titleContainerDistance = entryFieldContainer.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4)
@ -238,15 +235,13 @@ import UIKit
super.reset() super.reset()
backgroundColor = .clear backgroundColor = .clear
titleLabel.reset() isAccessibilityElement = false
feedbackLabel.reset() titleLabel.font = MFStyler.fontB3()
titleLabel.textColor = .mfBattleshipGrey()
feedbackLabel.font = MFStyler.fontForTextFieldUnderLabel()
feedbackLabel.textColor = .black
entryFieldContainer.reset() entryFieldContainer.reset()
} }
open func feedbackStandardMessage(_ message: String? = nil) {
feedback = message ?? standardMessage
}
} }
// MARK: - MVMCoreUIMoleculeViewProtocol // MARK: - MVMCoreUIMoleculeViewProtocol
@ -268,13 +263,12 @@ extension EntryField {
isEnabled = false isEnabled = false
} }
if let errMessage = dictionary[KeyErrorMessage] as? String {
errorMessage = errMessage
}
if let feedback = dictionary["feedback"] as? String { if let feedback = dictionary["feedback"] as? String {
self.standardMessage = feedback self.standardMessage = feedback
feedbackStandardMessage() }
if let errMessage = dictionary[KeyErrorMessage] as? String {
errorMessage = errMessage
} }
if let isLocked = dictionary["isLocked"] as? Bool { if let isLocked = dictionary["isLocked"] as? Bool {

View File

@ -52,7 +52,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Methods
//-------------------------------------------------- //--------------------------------------------------
@objc open override func setupFieldContainerContent(_ container: UIView) { @objc open override func setupFieldContainerContent(_ container: UIView) {
super.setupFieldContainerContent(container) super.setupFieldContainerContent(container)

View File

@ -184,6 +184,12 @@ import UIKit
layoutIfNeeded() layoutIfNeeded()
} }
open override func reset() {
super.reset()
textField.font = MFStyler.fontForTextField()
}
@objc deinit { @objc deinit {
setBothTextDelegates(to: nil) setBothTextDelegates(to: nil)
} }

View File

@ -34,7 +34,11 @@ import UIKit
didSet (oldState) { didSet (oldState) {
// Will not update if new state is the same as old. // Will not update if new state is the same as old.
if fieldState != oldState { if fieldState != oldState {
fieldState.setStateUI(for: self) DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.fieldState.setStateUI(for: self)
}
} }
} }
} }
@ -166,18 +170,6 @@ import UIKit
} }
} }
open override func reset() {
super.reset()
isEnabled = true
_isLocked = false
_isSelected = false
_showError = false
subviews.forEach { $0.removeFromSuperview() }
borderPath.removeAllPoints()
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Draw States // MARK: - Draw States
//-------------------------------------------------- //--------------------------------------------------