latest textfield development.
This commit is contained in:
parent
d0264d45eb
commit
d2fddaf769
@ -21,6 +21,8 @@
|
||||
0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; };
|
||||
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; };
|
||||
0A41BA7F23453A6400D4C0BC /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextField.swift */; };
|
||||
0A52C1492357B5380051AECD /* MdnTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321A72355062F00CB7F00 /* MdnTextField.swift */; };
|
||||
0A52C14A2358B57E0051AECD /* DigitTextBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A8321AE2355FE9500CB7F00 /* DigitTextBox.swift */; };
|
||||
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
|
||||
0A8321C523563D3500CB7F00 /* MFTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = D29DF24221E6A176003B2FB9 /* MFTextField.m */; };
|
||||
0A8321C623563D3800CB7F00 /* MFTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = D29DF24C21E6A177003B2FB9 /* MFTextField.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -1109,6 +1111,7 @@
|
||||
D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */,
|
||||
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
|
||||
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
|
||||
0A52C1492357B5380051AECD /* MdnTextField.swift in Sources */,
|
||||
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
|
||||
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
|
||||
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
|
||||
@ -1117,6 +1120,7 @@
|
||||
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,
|
||||
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */,
|
||||
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
|
||||
0A52C14A2358B57E0051AECD /* DigitTextBox.swift in Sources */,
|
||||
D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */,
|
||||
B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */,
|
||||
D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */,
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc protocol MFDigitTextBoxDelegate: NSObjectProtocol {
|
||||
@objc protocol DigitTextBoxDelegate: NSObjectProtocol {
|
||||
@objc optional func textFieldDidDelete(_ textField: UITextField?)
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ import UIKit
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
weak var mfTextBoxDelegate: MFDigitTextBoxDelegate?
|
||||
weak var textBoxDelegate: DigitTextBoxDelegate?
|
||||
|
||||
private var previousSize: CGFloat = 0.0
|
||||
|
||||
@ -85,18 +85,18 @@ import UIKit
|
||||
|
||||
override open func deleteBackward() {
|
||||
super.deleteBackward()
|
||||
|
||||
if let delegate = mfTextBoxDelegate {
|
||||
delegate.textFieldDidDelete?(self)
|
||||
}
|
||||
|
||||
textBoxDelegate?.textFieldDidDelete?(self)
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(self.previousSize)) {
|
||||
MFStyler.styleTextField(self)
|
||||
self.font = MFFonts.mfFont55Rg(28)
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let wSelf = self else { return }
|
||||
|
||||
if !MVMCoreGetterUtility.fequal(a: Float(size), b: Float(wSelf.previousSize)) {
|
||||
MFStyler.styleTextField(wSelf)
|
||||
self?.font = MFFonts.mfFont55Rg(28)
|
||||
|
||||
var digitWidth: CGFloat = 0
|
||||
var digitHeight: CGFloat = 0
|
||||
@ -115,9 +115,9 @@ import UIKit
|
||||
})
|
||||
|
||||
sizeObject?.performBlockBase(onSize: size)
|
||||
self.widthConstraint?.constant = digitWidth
|
||||
self.heightConstraint?.constant = digitHeight
|
||||
self.previousSize = size
|
||||
self?.widthConstraint?.constant = digitWidth
|
||||
self?.heightConstraint?.constant = digitHeight
|
||||
self?.previousSize = size
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -130,6 +130,7 @@ import UIKit
|
||||
}
|
||||
|
||||
func hideError() {
|
||||
|
||||
layer.borderColor = UIColor.mfSilver().cgColor
|
||||
bottomBar?.setAsMedium()
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class DigitTextField: TextField, UITextFieldDelegate, MFDigitTextBoxDelegate {
|
||||
|
||||
@objcMembers open class DigitTextField: TextField, UITextFieldDelegate, DigitTextBoxDelegate {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
@ -21,6 +22,7 @@ import UIKit
|
||||
|
||||
private var numberOfDigits = 0
|
||||
private var switchedAutomatically = false
|
||||
public var textFields: [DigitTextBox]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -33,43 +35,49 @@ import UIKit
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
func digitField() -> MFDigitTextBox? {
|
||||
let textField = MFDigitTextBox()
|
||||
textField.delegate = self
|
||||
textField.mfTextBoxDelegate = self
|
||||
return textField
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
class func withNumberOfDigits(_ numberOfDigits: Int) -> Self? {
|
||||
let field = self.mf()
|
||||
field?.numberOfDigits = numberOfDigits
|
||||
field?.buildTextFieldsView(forSize: MVMCoreUISplitViewController.getDetailViewWidth())
|
||||
return field
|
||||
|
||||
public init(dinumberOfDigits: Int) {
|
||||
super.init(frame: .zero)
|
||||
|
||||
numberOfDigits = dinumberOfDigits
|
||||
buildTextFieldsView(forSize: MVMCoreUISplitViewController.getDetailViewWidth())
|
||||
}
|
||||
|
||||
class func withNumberOfDigits(_ numberOfDigits: Int, withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?) -> Self? {
|
||||
let field = self.mfTextField(withBothDelegates: delegate)
|
||||
field?.numberOfDigits = numberOfDigits
|
||||
field?.buildTextFieldsView(forSize: MVMCoreUISplitViewController.getDetailViewWidth())
|
||||
return field
|
||||
|
||||
public init(numberOfDigits: Int, bothDelegates delegates: (UITextFieldDelegate & MFTextFieldDelegate)?) {
|
||||
super.init(bothDelegates: delegates as? (TextFieldDelegate & UITextFieldDelegate))
|
||||
|
||||
self.numberOfDigits = numberOfDigits
|
||||
buildTextFieldsView(forSize: MVMCoreUISplitViewController.getDetailViewWidth())
|
||||
}
|
||||
|
||||
class func withNumberOfDigits(_ numberOfDigits: Int, withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?, size: CGFloat) -> Self? {
|
||||
let field = self.mfTextField(withBothDelegates: delegate)
|
||||
field?.numberOfDigits = numberOfDigits
|
||||
field?.buildTextFieldsView(forSize: size)
|
||||
return field
|
||||
|
||||
public init(withNumberOfDigits numberOfDigits: Int, withBothDelegates delegate: (UITextFieldDelegate & MFTextFieldDelegate)?, size: CGFloat) {
|
||||
super.init(bothDelegates: delegate as? (TextFieldDelegate & UITextFieldDelegate))
|
||||
|
||||
self.numberOfDigits = numberOfDigits
|
||||
buildTextFieldsView(forSize: size)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
func digitField() -> DigitTextBox? {
|
||||
|
||||
let textField = DigitTextBox()
|
||||
textField.delegate = self
|
||||
textField.textBoxDelegate = self
|
||||
return textField
|
||||
}
|
||||
|
||||
func buildTextFieldsView(forSize size: CGFloat) {
|
||||
|
||||
// Remove all current UI.
|
||||
if let textFields = textFields, !textFields.isEmpt {
|
||||
StackableViewController.removeUIViews(self.textFields)
|
||||
if let textFields = textFields, !textFields.isEmpty {
|
||||
StackableViewController.remove(textFields)
|
||||
}
|
||||
|
||||
if numberOfDigits > 0 {
|
||||
@ -85,9 +93,7 @@ import UIKit
|
||||
textFields.append(textField)
|
||||
}
|
||||
}
|
||||
self.textFields = textFields as? [UITextField]
|
||||
|
||||
// Layout text boxes.
|
||||
self.textFields = textFields as? [DigitTextBox]
|
||||
setupTextFieldsView(forSize: size)
|
||||
|
||||
} else {
|
||||
@ -97,11 +103,16 @@ import UIKit
|
||||
|
||||
func setupTextFieldsView(forSize size: CGFloat) {
|
||||
|
||||
let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3).getValueBasedOnScreenSize()
|
||||
|
||||
|
||||
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize(),
|
||||
let textFieldsView = textFieldsView,
|
||||
let textFields = textFields
|
||||
else { return }
|
||||
|
||||
StackableViewController.populateViewHorizontally(textFieldsView, withUIArray: textFields, withSpacingBlock: { object in
|
||||
|
||||
let inset = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space)
|
||||
var inset = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space)
|
||||
|
||||
if self.textFields?.count == 1 {
|
||||
inset.left = 0
|
||||
@ -113,21 +124,67 @@ import UIKit
|
||||
} else if (object as? UITextField) == self.textFields?.last {
|
||||
inset.right = 0
|
||||
}
|
||||
|
||||
return inset
|
||||
})
|
||||
}
|
||||
|
||||
func valueChanged() {
|
||||
override func valueChanged() {
|
||||
super.valueChanged()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
if self.label.text.length > 0 {
|
||||
self.labelToTextFieldPin.constant = 10
|
||||
self?.labelToTextFieldPin?.constant = 10
|
||||
|
||||
} else {
|
||||
self.labelToTextFieldPin.constant = 0
|
||||
self?.labelToTextFieldPin?.constant = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
||||
self.formLabel.updateView(size)
|
||||
|
||||
// Remove all current UI.
|
||||
if (self.textFields?.count ?? 0) > 0 {
|
||||
StackableViewController.removeUIViews(self.textFields)
|
||||
}
|
||||
|
||||
// Update text boxes.
|
||||
for textField in self.textFields ?? [] {
|
||||
guard let textField = textField as? MFDigitTextBox else {
|
||||
continue
|
||||
}
|
||||
textField.updateView(size)
|
||||
}
|
||||
|
||||
// Layout text boxes.
|
||||
self.setupTextFieldsView(forSize: size)
|
||||
})
|
||||
}
|
||||
|
||||
func setupView() {
|
||||
super.setupView()
|
||||
formLabel.styleB2(true)
|
||||
self.formText = ""
|
||||
alignCenterHorizontal()
|
||||
}
|
||||
|
||||
// MARK: - Molecule
|
||||
func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
let digitsNumber = json?.optionalNumber(forKey: "digits")
|
||||
let digits = digitsNumber != nil ? digitsNumber?.intValue ?? 0 : 4
|
||||
if digits != numberOfDigits {
|
||||
numberOfDigits = digits
|
||||
buildTextFieldsView(forSize: MVMCoreUIUtility.getWidth())
|
||||
}
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,8 +118,6 @@
|
||||
}];
|
||||
}
|
||||
|
||||
// CONTINUE
|
||||
|
||||
- (void)updateView:(CGFloat)size {
|
||||
[super updateView:size];
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
@ -163,6 +161,8 @@
|
||||
return 44;
|
||||
}
|
||||
|
||||
// CONTINUE
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
- (NSString *)placeholder {
|
||||
|
||||
@ -21,11 +21,23 @@ import MVMCore
|
||||
public var isNationalMdn = false
|
||||
public var shouldValidateMDN = false
|
||||
|
||||
public var mdn: String? {
|
||||
get {
|
||||
guard let text = text else { return nil }
|
||||
|
||||
return MVMCoreUIUtility.removeMdnFormat(text)
|
||||
}
|
||||
set {
|
||||
guard let MDN = newValue else { return }
|
||||
text = MVMCoreUIUtility.formatMdn(MDN)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//--------------------------------------------------
|
||||
|
||||
open override init(frame: CGRect) {
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: .zero)
|
||||
setup()
|
||||
}
|
||||
@ -34,7 +46,7 @@ import MVMCore
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
@ -58,7 +70,7 @@ import MVMCore
|
||||
textField?.inputAccessoryView = toolbar
|
||||
}
|
||||
|
||||
// If you're using a MFViewController, you must set this to it
|
||||
// If you're using a MFViewController, you must set this to it.
|
||||
public override weak var uiTextFieldDelegate: UITextFieldDelegate? {
|
||||
get {
|
||||
return textField?.delegate
|
||||
@ -79,16 +91,17 @@ import MVMCore
|
||||
|
||||
func hasValidMdn() -> Bool {
|
||||
|
||||
guard let mdn = getMdn() else { return true }
|
||||
guard let MDN = mdn else { return true }
|
||||
|
||||
if mdn.isEmpty {
|
||||
if MDN.isEmpty {
|
||||
return true
|
||||
|
||||
} else if isNationalMdn {
|
||||
return MVMCoreUIUtility.validateMDNString(mdn)
|
||||
}
|
||||
|
||||
return MVMCoreUIUtility.validateInternationalMDNString(mdn)
|
||||
if isNationalMdn {
|
||||
return MVMCoreUIUtility.validateMDNString(MDN)
|
||||
}
|
||||
|
||||
return MVMCoreUIUtility.validateInternationalMDNString(MDN)
|
||||
}
|
||||
|
||||
func validateAndColor() -> Bool {
|
||||
@ -114,18 +127,6 @@ import MVMCore
|
||||
return nil
|
||||
}
|
||||
|
||||
func getMdn() -> String? {
|
||||
|
||||
return MVMCoreUIUtility.removeMdnFormat(text! as String)
|
||||
}
|
||||
|
||||
func setMdn(_ mdn: String?) {
|
||||
|
||||
guard let MDN = mdn else { return }
|
||||
|
||||
text = MVMCoreUIUtility.formatMdn(MDN)
|
||||
}
|
||||
|
||||
@objc func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
if let delegate = uiTextFieldDelegate {
|
||||
@ -149,7 +150,7 @@ import MVMCore
|
||||
// MARK: - ContactPicker Delegate
|
||||
//--------------------------------------------------
|
||||
|
||||
func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
|
||||
public func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
|
||||
|
||||
if contactProperty.value != nil && (contactProperty.value is CNPhoneNumber) {
|
||||
|
||||
@ -180,37 +181,29 @@ import MVMCore
|
||||
//--------------------------------------------------
|
||||
|
||||
@discardableResult
|
||||
@objc func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
@objc public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
|
||||
textField.resignFirstResponder()
|
||||
|
||||
if let customDelegate = customDelegate {
|
||||
return customDelegate.textFieldShouldReturn?(textField) ?? false
|
||||
}
|
||||
|
||||
return true
|
||||
return customDelegate?.textFieldShouldReturn?(textField) ?? true
|
||||
}
|
||||
|
||||
@objc func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
@objc public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
|
||||
|
||||
if !MVMCoreUIUtility.validate(string, withRegularExpression: RegularExpressionDigitOnly) {
|
||||
return false
|
||||
}
|
||||
|
||||
if let customDelegate = customDelegate {
|
||||
return customDelegate.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true
|
||||
}
|
||||
|
||||
return true
|
||||
return customDelegate?.textField?(textField, shouldChangeCharactersIn: range, replacementString: string) ?? true
|
||||
}
|
||||
|
||||
func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
public func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
|
||||
textField.text = MVMCoreUIUtility.removeMdnFormat(textField.text)
|
||||
customDelegate?.textFieldDidBeginEditing?(textField)
|
||||
}
|
||||
|
||||
func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
public func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
|
||||
customDelegate?.textFieldDidEndEditing?(textField)
|
||||
|
||||
@ -223,30 +216,18 @@ import MVMCore
|
||||
// MARK: - Passed Along TextField delegate
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||
@objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
|
||||
|
||||
if let customDelegate = customDelegate {
|
||||
return customDelegate.textFieldShouldBeginEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
return true
|
||||
return customDelegate?.textFieldShouldBeginEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
@objc func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
|
||||
@objc public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
|
||||
|
||||
if let customDelegate = customDelegate {
|
||||
return customDelegate.textFieldShouldEndEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
return true
|
||||
return customDelegate?.textFieldShouldEndEditing?(textField) ?? true
|
||||
}
|
||||
|
||||
@objc func textFieldShouldClear(_ textField: UITextField) -> Bool {
|
||||
@objc public func textFieldShouldClear(_ textField: UITextField) -> Bool {
|
||||
|
||||
if let customDelegate = customDelegate {
|
||||
return customDelegate.textFieldShouldClear?(textField) ?? true
|
||||
}
|
||||
|
||||
return true
|
||||
return customDelegate?.textFieldShouldClear?(textField) ?? true
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,11 +11,11 @@ import UIKit
|
||||
|
||||
@objc public protocol TextFieldDelegate: NSObjectProtocol {
|
||||
/// Called when the entered text becomes valid based on the validation block
|
||||
@objc optional func isValid(_ textfield: TextField?)
|
||||
@objc optional func isValid(textfield: TextField?)
|
||||
/// Called when the entered text becomes invalid based on the validation block
|
||||
@objc optional func isInvalid(_ textfield: TextField?)
|
||||
@objc optional func isInvalid(textfield: TextField?)
|
||||
/// Dismisses the keyboard.
|
||||
@objc optional func dismissField(_ sender: Any?)
|
||||
@objc optional func dismissField(sender: Any?)
|
||||
}
|
||||
|
||||
@objcMembers open class TextField: ViewConstrainingView {
|
||||
@ -31,6 +31,11 @@ import UIKit
|
||||
public var placeholderErrorLabel: Label?
|
||||
public var dashLine: DashLine?
|
||||
public var dropDownCarrotLabel: UILabel?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Accessories
|
||||
//--------------------------------------------------
|
||||
|
||||
public weak var datePicker: UIDatePicker?
|
||||
private(set) weak var toolbar: UIToolbar?
|
||||
|
||||
@ -55,7 +60,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
// If you're using a MFViewController, you must set this to it
|
||||
/// If you're using a MFViewController, you must set this to it
|
||||
public weak var uiTextFieldDelegate: UITextFieldDelegate? {
|
||||
get {
|
||||
return textField?.delegate
|
||||
@ -69,14 +74,21 @@ import UIKit
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
private var borderPath: UIBezierPath?
|
||||
private var calendar: Calendar?
|
||||
public var pickerView: UIPickerView?
|
||||
public var observingForChanges = false
|
||||
public var errorShowing = false
|
||||
public var showError = false
|
||||
public var hasDropDown = false
|
||||
public var enabled = true
|
||||
public var hideBorder = false
|
||||
public var isEnabled = true
|
||||
|
||||
private var borderPath: UIBezierPath?
|
||||
|
||||
/// Determines if a border should be drawn.
|
||||
public var hideBorder = false {
|
||||
didSet {
|
||||
setNeedsLayout()
|
||||
}
|
||||
}
|
||||
|
||||
public var text: String? {
|
||||
get {
|
||||
@ -100,6 +112,7 @@ import UIKit
|
||||
|
||||
public var placeholderTextColor: UIColor = .black
|
||||
|
||||
/// Setgs placeholder text in the textField.
|
||||
public var placeholder: String? {
|
||||
get {
|
||||
guard let attributedPlaceholder = textField?.attributedPlaceholder else { return nil }
|
||||
@ -113,7 +126,7 @@ import UIKit
|
||||
|
||||
textField?.attributedPlaceholder = NSAttributedString(string: newPlaceholderText, attributes: [NSAttributedString.Key.foregroundColor: placeholderTextColor])
|
||||
|
||||
if !errorShowing {
|
||||
if !showError {
|
||||
placeholderErrorLabel?.text = (textField?.text?.count ?? 0) > 0 ? newPlaceholderText : ""
|
||||
}
|
||||
|
||||
@ -121,7 +134,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
public var formatter: DateFormatter? {
|
||||
public var formatter: DateFormatter = {
|
||||
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
@ -130,7 +143,7 @@ import UIKit
|
||||
formatter.formatterBehavior = .default
|
||||
|
||||
return formatter
|
||||
}
|
||||
}()
|
||||
|
||||
public var isValid = false
|
||||
public var fieldKey: String?
|
||||
@ -143,27 +156,7 @@ import UIKit
|
||||
public var enabledTextColor: UIColor?
|
||||
public var disabledTextColor: UIColor?
|
||||
|
||||
public var errorMessage: String? {
|
||||
didSet {
|
||||
|
||||
guard enabled else { return }
|
||||
|
||||
self.separatorHeightConstraint?.constant = 4
|
||||
self.errorShowing = true
|
||||
self.separatorView?.backgroundColor = UIColor.mfPumpkin()
|
||||
|
||||
if let errorMessage = self.errorMessage {
|
||||
self.placeholderErrorLabel?.text = errorMessage
|
||||
self.placeholderErrorLabel?.numberOfLines = 0
|
||||
self.textField?.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", self.textField?.text ?? "", errorMessage)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.setNeedsDisplay()
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
public var errorMessage: String?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
@ -190,33 +183,32 @@ import UIKit
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
setupView()
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
/// Basic initializer.
|
||||
public convenience init() {
|
||||
self.init(frame: .zero)
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
/// - parameter bothDelegates: Sets both MF/UI Text Field Delegates.
|
||||
public convenience init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) {
|
||||
self.init(frame: .zero)
|
||||
|
||||
public init(bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) {
|
||||
super.init(frame: .zero)
|
||||
setupView()
|
||||
setBothTextFieldDelegates(bothDelegates)
|
||||
}
|
||||
|
||||
/// - parameter hasDropDown: tbd
|
||||
/// - parameter map: Dictionary of values to setup this TextField
|
||||
/// - parameter bothDelegate: Sets both MF/UI Text Field Delegates.
|
||||
public convenience init(hasDropDown: Bool = false, map: [AnyHashable: Any]?, bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) {
|
||||
self.init(frame: .zero)
|
||||
|
||||
public init(hasDropDown: Bool = false, map: [AnyHashable: Any]?, bothDelegates: (UITextFieldDelegate & TextFieldDelegate)?) {
|
||||
super.init(frame: .zero)
|
||||
setupView()
|
||||
dropDownCarrotLabel?.isHidden = hasDropDown
|
||||
self.hasDropDown = !hasDropDown
|
||||
setWithMap(map, bothDelegates: bothDelegates)
|
||||
@ -367,15 +359,14 @@ import UIKit
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
self?.formLabel?.updateView(size)
|
||||
self?.placeholderErrorLabel?.font = MFStyler.fontForTextFieldUnderLabel()
|
||||
if let textField = self?.textField {
|
||||
MFStyler.styleTextField(textField)
|
||||
}
|
||||
self?.dashLine?.updateView(size)
|
||||
formLabel?.updateView(size)
|
||||
placeholderErrorLabel?.font = MFStyler.fontForTextFieldUnderLabel()
|
||||
if let textField = textField {
|
||||
MFStyler.styleTextField(textField)
|
||||
}
|
||||
dashLine?.updateView(size)
|
||||
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -397,7 +388,7 @@ import UIKit
|
||||
borderPath?.addLine(to: CGPoint(x: frame.origin.x + frame.size.width, y: frame.origin.y + frame.size.height))
|
||||
borderPath?.lineWidth = 1
|
||||
|
||||
let strokeColor = errorShowing ? UIColor.mfPumpkin() : UIColor.mfSilver()
|
||||
let strokeColor = showError ? UIColor.mfPumpkin() : UIColor.mfSilver()
|
||||
strokeColor.setStroke()
|
||||
|
||||
borderPath?.stroke()
|
||||
@ -428,7 +419,7 @@ import UIKit
|
||||
if let calendar = calendar, calendar.isDate(fromDate, inSameDayAs: Date()) {
|
||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||
} else {
|
||||
self.text = formatter?.string(from: fromDate)
|
||||
self.text = formatter.string(from: fromDate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,7 +433,7 @@ import UIKit
|
||||
if let calendar = calendar, calendar.isDate(fromDate, inSameDayAs: Date()) {
|
||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||
} else {
|
||||
text = formatter?.string(from: fromDate)
|
||||
text = formatter.string(from: fromDate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,7 +450,7 @@ import UIKit
|
||||
if let calendar = calendar, calendar.isDate(pickedDate, inSameDayAs: Date()) {
|
||||
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
|
||||
} else {
|
||||
text = formatter?.string(from: pickedDate)
|
||||
text = formatter.string(from: pickedDate)
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,13 +467,43 @@ import UIKit
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
func showErrorDropdown(_ show: Bool) {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
self?.showError = show
|
||||
self?.separatorHeightConstraint?.constant = show ? 4 : 1
|
||||
self?.separatorView?.backgroundColor = show ? UIColor.mfPumpkin() : .black
|
||||
self?.setNeedsDisplay()
|
||||
self?.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
func showErrorMessage(_ errorMessage: String?) {
|
||||
|
||||
guard isEnabled else { return }
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
self?.separatorHeightConstraint?.constant = 4
|
||||
self?.showError = true
|
||||
self?.separatorView?.backgroundColor = UIColor.mfPumpkin()
|
||||
self?.placeholderErrorLabel?.text = errorMessage
|
||||
self?.placeholderErrorLabel?.numberOfLines = 0
|
||||
self?.textField?.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textfield_error_message") ?? "", self?.textField?.text ?? "", self?.errorMessage ?? "")
|
||||
self?.setNeedsDisplay()
|
||||
self?.layoutIfNeeded()
|
||||
self?.showErrorDropdown(self?.showError ?? false)
|
||||
}
|
||||
}
|
||||
|
||||
public func hideError() {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.separatorHeightConstraint?.constant = 1
|
||||
self?.separatorView?.backgroundColor = .black
|
||||
self?.layoutIfNeeded()
|
||||
self?.errorShowing = false
|
||||
self?.showError = false
|
||||
self?.placeholderErrorLabel?.textColor = .black
|
||||
self?.placeholderErrorLabel?.text = ""
|
||||
self?.textField?.accessibilityValue = nil
|
||||
@ -517,6 +538,10 @@ import UIKit
|
||||
self.errorMessage = errMessage
|
||||
}
|
||||
|
||||
if let hideBorder = map["hideBorder"] as? Bool {
|
||||
self.hideBorder = hideBorder
|
||||
}
|
||||
|
||||
// Key used to send text value to server
|
||||
if let fieldKey = map[KeyFieldKey] as? String {
|
||||
self.fieldKey = fieldKey
|
||||
@ -595,7 +620,7 @@ import UIKit
|
||||
public func isEnabled(_ enable: Bool) {
|
||||
|
||||
// Set outside the dispatch so that registerAnimations can know about it
|
||||
enabled = enable
|
||||
isEnabled = enable
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
@ -607,7 +632,7 @@ import UIKit
|
||||
self?.textField?.textColor = self?.enabledTextColor ?? .black
|
||||
self?.formLabel?.textColor = UIColor.mfBattleshipGrey()
|
||||
self?.placeholderErrorLabel?.textColor = .black
|
||||
self?.separatorView?.backgroundColor = (self?.errorShowing ?? false) ? UIColor.mfPumpkin() : .black
|
||||
self?.separatorView?.backgroundColor = (self?.showError ?? false) ? UIColor.mfPumpkin() : .black
|
||||
self?.showDropDown(true)
|
||||
|
||||
} else {
|
||||
@ -640,7 +665,7 @@ import UIKit
|
||||
func valueChanged() {
|
||||
|
||||
// Update label for placeholder
|
||||
if !errorShowing {
|
||||
if !showError {
|
||||
placeholderErrorLabel?.text = ""
|
||||
}
|
||||
|
||||
@ -651,17 +676,17 @@ import UIKit
|
||||
|
||||
if previousValidity && !isValid {
|
||||
if let errMessage = errorMessage {
|
||||
self.errorMessage = errMessage
|
||||
showErrorMessage(errMessage)
|
||||
}
|
||||
|
||||
if let mfTextFieldDelegate = mfTextFieldDelegate {
|
||||
mfTextFieldDelegate.isInvalid?(self)
|
||||
mfTextFieldDelegate.isInvalid?(textfield: self)
|
||||
}
|
||||
} else if !previousValidity && isValid {
|
||||
hideError()
|
||||
|
||||
if let mfTextFieldDelegate = mfTextFieldDelegate {
|
||||
mfTextFieldDelegate.isValid?(self)
|
||||
mfTextFieldDelegate.isValid?(textfield: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -672,18 +697,14 @@ import UIKit
|
||||
hideError()
|
||||
separatorView?.backgroundColor = .black
|
||||
} else if let errMessage = errorMessage {
|
||||
self.errorMessage = errMessage
|
||||
showErrorMessage(errMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func startEditing() {
|
||||
|
||||
textField?.becomeFirstResponder()
|
||||
|
||||
if !errorShowing {
|
||||
separatorView?.backgroundColor = .black
|
||||
separatorHeightConstraint?.constant = 1
|
||||
}
|
||||
showErrorDropdown(!showError)
|
||||
}
|
||||
|
||||
class func getEnabledTextfields(_ textFieldToDetermine: [MFTextField]?) -> [AnyHashable]? {
|
||||
@ -722,7 +743,7 @@ extension TextField {
|
||||
}
|
||||
}
|
||||
|
||||
override open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
override open class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 76
|
||||
}
|
||||
}
|
||||
@ -730,10 +751,6 @@ extension TextField {
|
||||
// MARK: - Accessibility
|
||||
extension TextField {
|
||||
|
||||
// open override class func accessibilityElements() -> [Any]? {
|
||||
// return [self.textField]
|
||||
// }
|
||||
|
||||
func pushAccessibilityNotification() {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
Loading…
Reference in New Issue
Block a user