Further development of Entry Field.
This commit is contained in:
parent
59008f87d0
commit
44ff5e9d3c
@ -22,7 +22,6 @@ import UIKit
|
||||
return calendar
|
||||
}()
|
||||
|
||||
// TODO: Pull this out into Styler or some class akin to it.
|
||||
public var formatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
@ -38,7 +37,6 @@ import UIKit
|
||||
|
||||
@objc public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
setup()
|
||||
}
|
||||
|
||||
@objc public convenience init() {
|
||||
@ -58,7 +56,8 @@ import UIKit
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc private func setup() {
|
||||
public override func setupFieldContainerContent(_ container: UIView) {
|
||||
super.setupFieldContainerContent(container)
|
||||
|
||||
datePicker = MVMCoreUICommonViewsUtility.addDatePicker(to: textField)
|
||||
datePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged)
|
||||
@ -81,7 +80,7 @@ import UIKit
|
||||
let pickedDate = datePicker?.date
|
||||
setTextWith(date: pickedDate)
|
||||
|
||||
textField.resignFirstResponder()
|
||||
resignFirstResponder()
|
||||
return pickedDate
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,9 @@ import UIKit
|
||||
|
||||
private var previousSize: CGFloat = 0.0
|
||||
|
||||
// Default dimensions of the DigitBox
|
||||
static let size: CGSize = CGSize(width: 39, height: 44)
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
@ -97,7 +100,7 @@ import UIKit
|
||||
guard constraints.isEmpty else { return }
|
||||
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
backgroundColor = .white
|
||||
backgroundColor = .clear
|
||||
|
||||
addSubview(digitField)
|
||||
digitField.delegate = self
|
||||
@ -112,9 +115,9 @@ import UIKit
|
||||
digitField.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||
digitField.centerXAnchor.constraint(equalTo: centerXAnchor)])
|
||||
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: 39)
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: DigitBox.size.width)
|
||||
widthConstraint?.isActive = true
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: 44)
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: DigitBox.size.height)
|
||||
heightConstraint?.isActive = true
|
||||
|
||||
if let bottomBar = bottomBar {
|
||||
|
||||
@ -105,7 +105,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Sets the text of titleLabel
|
||||
public var title: String? {
|
||||
get { return titleLabel.text }
|
||||
@ -177,10 +177,10 @@ import UIKit
|
||||
|
||||
/// Initial configuration of class and view.
|
||||
@objc final public override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
guard subviews.isEmpty else { return }
|
||||
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
isAccessibilityElement = false
|
||||
setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
accessibilityElements = [titleLabel, feedbackLabel]
|
||||
|
||||
@ -97,23 +97,22 @@ import MVMCore
|
||||
return MVMCoreUIUtility.validateInternationalMDNString(MDN)
|
||||
}
|
||||
|
||||
@objc public func validate() -> Bool {
|
||||
@objc public override func validateTextField() -> Bool {
|
||||
|
||||
if !shouldValidateMDN {
|
||||
let isValid = hasValidMDN()
|
||||
guard !shouldValidateMDN else { return true }
|
||||
|
||||
let isValid = hasValidMDN()
|
||||
|
||||
if isValid {
|
||||
showError = false
|
||||
|
||||
if isValid {
|
||||
showError = false
|
||||
} else {
|
||||
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
showError = true
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField)
|
||||
}
|
||||
|
||||
return isValid
|
||||
} else {
|
||||
errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message")
|
||||
showError = true
|
||||
UIAccessibility.post(notification: .layoutChanged, argument: textField)
|
||||
}
|
||||
|
||||
return true
|
||||
return isValid
|
||||
}
|
||||
|
||||
@objc public func getContacts(_ sender: Any?) {
|
||||
@ -183,7 +182,7 @@ import MVMCore
|
||||
|
||||
proprietorTextDelegate?.textFieldDidEndEditing?(textField)
|
||||
|
||||
if validate() && isNationalMDN {
|
||||
if validateTextField() && isNationalMDN {
|
||||
textField.text = MVMCoreUIUtility.formatMdn(textField.text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,13 @@ import UIKit
|
||||
/// Set enabled and disabled colors to be utilized when setting this texfield's isEnabled property.
|
||||
public var textColor: (enabled: UIColor?, disabled: UIColor?) = (.black, .mfSilver())
|
||||
|
||||
public var observingForChange: Bool = false
|
||||
private var observingForChange: Bool = false
|
||||
|
||||
/// Validate on each entry in the textField. Default: false
|
||||
public var validateEachCharacter: Bool = false
|
||||
|
||||
/// Validate when user resigns editing. Default: true
|
||||
public var validateWhenDoneEditing: Bool = true
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
@ -75,7 +81,6 @@ import UIKit
|
||||
get { return textField.text }
|
||||
set {
|
||||
textField.text = newValue
|
||||
valueChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +106,7 @@ import UIKit
|
||||
// MARK: - Delegate Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
/// The delegate and block for validation. Validates if the text that the user has entered is valid or not. Checked after each change if there is a delegate.
|
||||
/// The delegate and block for validation. Validates if the text that the user has entered.
|
||||
public weak var observingTextFieldDelegate: ObservingTextFieldDelegate? {
|
||||
didSet {
|
||||
if observingTextFieldDelegate != nil && !observingForChange {
|
||||
@ -193,33 +198,30 @@ import UIKit
|
||||
// MARK: - Observing for Change (TextFieldDelegate)
|
||||
//--------------------------------------------------
|
||||
|
||||
public func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
guard let enteredValue = enteredValue else { return false }
|
||||
return enteredValue.count > 0
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
@objc override open func resignFirstResponder() -> Bool {
|
||||
|
||||
if validateWhenDoneEditing {
|
||||
validateTextField()
|
||||
}
|
||||
|
||||
textField.resignFirstResponder()
|
||||
isSelected = false
|
||||
return true
|
||||
}
|
||||
|
||||
@objc func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
_ = resignFirstResponder()
|
||||
}
|
||||
|
||||
public func defaultValidationBlock() {
|
||||
|
||||
validationBlock = { enteredValue in
|
||||
return (enteredValue?.count ?? 0) > 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidChangeNotification
|
||||
@objc func valueChanged() {
|
||||
|
||||
if !showError {
|
||||
feedback = ""
|
||||
}
|
||||
/// Validates the text of the entry field.
|
||||
@discardableResult
|
||||
@objc public func validateTextField() -> Bool {
|
||||
|
||||
// If validation not set, input will always be valid
|
||||
isValid = validationBlock?(text) ?? true
|
||||
|
||||
if !isValid {
|
||||
@ -227,22 +229,10 @@ import UIKit
|
||||
observingTextFieldDelegate?.isInvalid?(textfield: self)
|
||||
|
||||
} else if isValid {
|
||||
if showError == true {
|
||||
showError = false
|
||||
}
|
||||
isSelected = true
|
||||
observingTextFieldDelegate?.isValid?(textfield: self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidEndEditingNotification
|
||||
@objc func endInputing() {
|
||||
|
||||
if isValid {
|
||||
showError = false
|
||||
entryFieldContainer.bottomBar?.backgroundColor = UIColor.black.cgColor
|
||||
|
||||
}
|
||||
return isValid
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidBeginEditingNotification
|
||||
@ -251,9 +241,33 @@ import UIKit
|
||||
isSelected = true
|
||||
textField.becomeFirstResponder()
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidChangeNotification (every character entry)
|
||||
@objc func valueChanged() {
|
||||
|
||||
guard validateEachCharacter else { return }
|
||||
|
||||
validateTextField()
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidEndEditingNotification
|
||||
@objc func endInputing() {
|
||||
|
||||
if isValid {
|
||||
showError = false
|
||||
entryFieldContainer.bottomBar?.backgroundColor = UIColor.black.cgColor
|
||||
}
|
||||
|
||||
resignFirstResponder()
|
||||
}
|
||||
|
||||
@objc func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
resignFirstResponder()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Molecular
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
extension TextEntryField {
|
||||
|
||||
@objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
@ -44,7 +44,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
/// MARK:- MVMCoreViewProtocol
|
||||
// MARK:- MVMCoreViewProtocol
|
||||
extension View: MVMCoreViewProtocol {
|
||||
|
||||
open func updateView(_ size: CGFloat) {}
|
||||
@ -56,7 +56,7 @@ extension View: MVMCoreViewProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
/// MARK:- MVMCoreUIMoleculeViewProtocol
|
||||
// MARK:- MVMCoreUIMoleculeViewProtocol
|
||||
extension View: MVMCoreUIMoleculeViewProtocol {
|
||||
|
||||
open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
|
||||
@ -33,8 +33,9 @@ import UIKit
|
||||
private(set) var fieldState: FieldState = .original {
|
||||
didSet (oldState) {
|
||||
// Will not update if new state is the same as old.
|
||||
guard fieldState != oldState else { return }
|
||||
fieldState.setStateUI(for: self)
|
||||
if fieldState != oldState {
|
||||
fieldState.setStateUI(for: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,8 +101,8 @@ import UIKit
|
||||
_isLocked = false
|
||||
_isEnabled = true
|
||||
|
||||
if selected && showError {
|
||||
fieldState = .selectedError
|
||||
if _showError {
|
||||
fieldState = selected ? .selectedError : .error
|
||||
} else {
|
||||
fieldState = selected ? .selected : .original
|
||||
}
|
||||
@ -174,6 +175,7 @@ import UIKit
|
||||
_showError = false
|
||||
|
||||
subviews.forEach { $0.removeFromSuperview() }
|
||||
borderPath.removeAllPoints()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -277,10 +279,10 @@ import UIKit
|
||||
layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Molecular
|
||||
//--------------------------------------------------
|
||||
}
|
||||
|
||||
// MARK:- MVMCoreUIMoleculeViewProtocol
|
||||
extension EntryFieldContainer {
|
||||
|
||||
override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user