Merge branch 'feature/swiftified_textField' of gitlab.verizon.com:BPHV_MIPS/mvm_core_ui into feature/swiftified_textField

# Conflicts:
#	MVMCoreUI/Atoms/TextFields/DigitEntryField.swift
This commit is contained in:
Kevin G Christiano 2019-11-19 10:07:24 -05:00
commit 702dc10db2
3 changed files with 118 additions and 116 deletions

View File

@ -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
// }
//}

View File

@ -17,7 +17,7 @@ import UIKit
//--------------------------------------------------
private(set) var numberOfDigits = 4
private var switchedAutomatically = false
public var switchFieldsAutomatically = false
public var digitFields: [DigitBox] = []
@ -31,7 +31,6 @@ import UIKit
digitFields.forEach {
$0.isEnabled = self.isEnabled
$0.isUserInteractionEnabled = isEnabled
$0.digitField.isEnabled = isEnabled
$0.digitField.textColor = isEnabled ? .black : .mfBattleshipGrey()
@ -42,7 +41,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 +56,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 +76,6 @@ import UIKit
public override var text: String? {
get {
var string = ""
digitFields.forEach { string += $0.digitField.text ?? "" }
return string
@ -109,9 +106,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,11 +129,10 @@ import UIKit
alignCenterHorizontal()
isAccessibilityElement = false
entryContainer.hideBorders = 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())
textField.removeFromSuperview()
assembleDigitFieldsView(size: MVMCoreUISplitViewController.getDetailViewWidth())
}
private func createDigitField() -> DigitBox {
@ -149,12 +144,16 @@ import UIKit
return digitBox
}
func setupDigitFieldsView(size: CGFloat) {
func assembleDigitFieldsView(size: CGFloat) {
var accessibleElements: [Any] = [titleLabel]
if numberOfDigits > 0 {
let digitFields = [DigitBox](repeating: createDigitField(), count: numberOfDigits)
var digitFields = [DigitBox]()
for _ in 0..<numberOfDigits {
digitFields.append(createDigitField())
}
self.digitFields = digitFields
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
@ -163,10 +162,9 @@ import UIKit
for (index, box) in digitFields.enumerated() {
accessibleElements.append(box)
entryContainer.addSubview(box)
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
@ -195,6 +193,8 @@ import UIKit
open override func updateView(_ size: CGFloat) {
super.updateView(size)
entryContainer.hideBorders = true
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
@ -203,34 +203,14 @@ 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) {
public func setAsSecureTextEntry(_ secureEntry: Bool) {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
@ -253,58 +233,54 @@ import UIKit
}
}
public func selectPreviousTextField(_ currentTextField: UITextField?, clear: Bool) {
public func selectPreviousDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectNextField = false
for field in digitFields {
if field == currentTextField {
if field.digitField == currentTextField {
selectNextField = true
field.isSelected = false
} else if selectNextField {
if !clear {
switchedAutomatically = true
switchFieldsAutomatically = true
}
field.becomeFirstResponder()
switchedAutomatically = false
field.digitField.becomeFirstResponder()
field.isSelected = true
switchFieldsAutomatically = false
UIAccessibility.post(notification: .layoutChanged, argument: field)
UIAccessibility.post(notification: .layoutChanged, argument: field.digitField)
}
}
}
public func selectNextTextField(_ currentTextField: UITextField?, clear: Bool) {
public func selectNextDigitField(_ currentTextField: UITextField?, clear: Bool) {
var selectNextField = false
for field in digitFields {
if field == currentTextField {
if field.digitField == currentTextField {
selectNextField = true
field.isSelected = false
} else if selectNextField {
if !clear {
switchedAutomatically = true
switchFieldsAutomatically = true
}
field.isSelected = true
field.becomeFirstResponder()
switchedAutomatically = false
switchFieldsAutomatically = false
UIAccessibility.post(notification: .layoutChanged, argument: field)
UIAccessibility.post(notification: .layoutChanged, argument: field.digitField)
}
}
}
class func getEnabledTextfields(_ textFieldToDetermine: [DigitBox]?) -> [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 }
}
}
@ -336,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
@ -356,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()
}
@ -376,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
}
@ -394,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)
@ -405,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)
}
}
setupDigitFieldsView(size: MVMCoreUIUtility.getWidth())
}
open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
return 44
return 115
}
}

View File

@ -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
}
}
}