further textviewfield development

This commit is contained in:
Kevin G Christiano 2020-05-07 14:41:50 -04:00
parent fcca1e3e83
commit efe3f95746
5 changed files with 248 additions and 43 deletions

View File

@ -9,7 +9,7 @@
import UIKit
class TextViewEntryField: EntryField {
class TextViewEntryField: EntryField, UITextViewDelegate {
//--------------------------------------------------
// MARK: - Outlets
//--------------------------------------------------
@ -26,12 +26,137 @@ class TextViewEntryField: EntryField {
return textView
}()
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------
/// Validate on each entry in the textField. Default: true
public var validateEachCharacter: Bool = true
public var textViewEntryFieldModel: TextViewEntryFieldModel? {
return model as? TextViewEntryFieldModel
}
public override var isEnabled: Bool {
get { return super.isEnabled }
set (enabled) {
super.isEnabled = enabled
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.textView.isEnabled = enabled
self.textView.textColor = enabled ? self.textEntryFieldModel?.enabledTextColor.uiColor : self.textEntryFieldModel?.disabledTextColor.uiColor
}
}
}
public override var showError: Bool {
get { return super.showError }
set (error) {
if error {
textView.accessibilityValue = String(format: MVMCoreUIUtility.hardcodedString(withKey: "textView_error_message") ?? "", textView.text ?? "", entryFieldModel?.errorMessage ?? "")
} else {
textView.accessibilityValue = nil
}
if textView.isSecureTextEntry {
// showErrorView(error)
}
super.showError = error
}
}
/// The text of this textView.
open override var text: String? {
get { return textView.text }
set {
textView.text = newValue
textViewEntryFieldModel?.text = newValue
}
}
/// Placeholder access for the textView.
public var placeholder: String? {
get {
// return textView.placeholder
return textViewEntryFieldModel?.placeholder
}
set {
// textView.placeholder = newValue
textViewEntryFieldModel?.placeholder = newValue
}
}
/// Executes on UITextField.textDidBeginEditingNotification
@objc func startEditing() {
isSelected = true
textView.becomeFirstResponder()
}
/// Executes on UITextField.textDidChangeNotification (each character entry)
@objc func valueChanged() {
guard validateEachCharacter else { return }
isSelected = true
validateTextField()
}
/// Validates the text of the entry field.
@objc public func validateTextField() {
text = textField.text
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
}
/// Executes on UITextField.textDidEndEditingNotification
@objc func endInputing() {
resignFirstResponder()
if isValid {
showError = false
entryFieldContainer.bottomBar?.backgroundColor = UIColor.mvmBlack.cgColor
}
}
@objc public func dismissFieldInput(_ sender: Any?) {
resignFirstResponder()
}
//--------------------------------------------------
// MARK: - Constraint
//--------------------------------------------------
public var heightConstraint: NSLayoutConstraint?
//--------------------------------------------------
// MARK: - Delegate Properties
//--------------------------------------------------
/// 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 {
observingForChange = true
NotificationCenter.default.addObserver(self, selector: #selector(valueChanged), name: UITextView.textDidChangeNotification, object: textView)
NotificationCenter.default.addObserver(self, selector: #selector(endInputing), name: UITextView.textDidEndEditingNotification, object: textView)
NotificationCenter.default.addObserver(self, selector: #selector(startEditing), name: UITextView.textDidBeginEditingNotification, object: textView)
} else if observingTextFieldDelegate == nil && observingForChange {
observingForChange = false
NotificationCenter.default.removeObserver(self, name: UITextView.textDidChangeNotification, object: textView)
NotificationCenter.default.removeObserver(self, name: UITextView.textDidEndEditingNotification, object: textView)
NotificationCenter.default.removeObserver(self, name: UITextView.textDidBeginEditingNotification, object: textView)
}
}
}
/// If you're using a ViewController, you must set this to it
public weak var uiTextViewDelegate: UITextViewDelegate? {
get { return textView.delegate }
set { textView.delegate = newValue }
}
//--------------------------------------------------
// MARK: - Lifecycle
@ -50,13 +175,13 @@ class TextViewEntryField: EntryField {
])
heightConstraint = textView.heightAnchor.constraint(equalToConstant: 0)
heightConstraint?.isActive = true
// textView.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
// textView.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
//
// let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
// entryFieldContainer.addGestureRecognizer(tap)
// textView.addTarget(self, action: #selector(startEditing), for: .editingDidBegin)
// textView.addTarget(self, action: #selector(dismissFieldInput), for: .editingDidEnd)
//
// let tap = UITapGestureRecognizer(target: self, action: #selector(startEditing))
// entryFieldContainer.addGestureRecognizer(tap)
accessibilityElements = [titleLabel, textView, feedbackLabel]
}
@ -72,6 +197,7 @@ class TextViewEntryField: EntryField {
super.reset()
textView.font = Styler.Font.RegularBodyLarge.getFont()
heightConstraint?.constant = 0
}
@ -84,18 +210,13 @@ class TextViewEntryField: EntryField {
guard let model = model as? TextViewEntryFieldModel else { return }
heightConstraint?.isActive = false
if let height = model.height {
heightConstraint?.constant = height
heightConstraint?.isActive = true
}
heightConstraint?.constant = model.height ?? 0
textView.isEditable = model.editable
// textView.isEditable = model.editable
textView.textAlignment = model.textAlignment
textView.textColor = model.enabledTextColor.uiColor
// textView.hideBorders = model.hideBorders
text = model.text
textView.uiTextViewDelegate = delegateObject?.uiTextViewDelegate
uiTextViewDelegate = delegateObject?.uiTextViewDelegate
if let accessibilityText = model.accessibilityText {
accessibilityLabel = accessibilityText
@ -115,10 +236,10 @@ class TextViewEntryField: EntryField {
textView.font = model.fontStyle.getFont()
textView.setPlaceholderIfAvailable()
if isEditable {
if textView.isEditable {
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
let observingDelegate = delegateObject?.uiTextViewDelegate ?? self
inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
textView.inputAccessoryView = UIToolbar.getToolbarWithDoneButton(delegate: observingDelegate,
action: #selector(textView.dismissFieldInput))
if (model.selected ?? false) && !model.wasInitiallySelected {

View File

@ -8,6 +8,7 @@
import UIKit
class TextViewEntryFieldModel: TextEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
@ -19,14 +20,11 @@ class TextViewEntryFieldModel: TextEntryFieldModel {
public var accessibilityText: String?
public var fontStyle: Styler.Font = Styler.Font.RegularBodySmall
public var textAlignment: NSTextAlignment = .left
public var height: CGFloat?
public var textAlignment: NSTextAlignment = .left
public var placeholderTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro
public var showsPlaceholder: Bool = false
public var hideBorders: Bool = false
public var editable: Bool = true
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
@ -37,7 +35,6 @@ class TextViewEntryFieldModel: TextEntryFieldModel {
case fontStyle
case textAlignment
case height
case hideBorders
case placeholderFontStyle
case placeholderTextColor
case editable
@ -63,14 +60,6 @@ class TextViewEntryFieldModel: TextEntryFieldModel {
self.textAlignment = textAlignment
}
if let hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) {
self.hideBorders = hideBorders
}
if let editable = try typeContainer.decodeIfPresent(Bool.self, forKey: .editable) {
self.editable = editable
}
if let fontStyle = try typeContainer.decodeIfPresent(Styler.Font.self, forKey: .fontStyle) {
self.fontStyle = fontStyle
}
@ -85,11 +74,10 @@ class TextViewEntryFieldModel: TextEntryFieldModel {
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(height, forKey: .height)
try container.encode(fontStyle, forKey: .fontStyle)
try container.encode(hideBorders, forKey: .hideBorders)
try container.encode(text, forKey: .text)
try container.encode(placeholderFontStyle, forKey: .placeholderFontStyle)
try container.encode(placeholderTextColor, forKey: .placeholderTextColor)
try container.encode(textAlignment, forKey: .textAlignment)
try container.encode(editable, forKey: .editable)
}
}

View File

@ -52,7 +52,7 @@ import Foundation
try? ModelRegistry.register(LabelAttributeActionModel.self)
// TextView
MoleculeObjectMapping.shared()?.register(viewClass: TextView.self, viewModelClass: TextViewModel.self)
MoleculeObjectMapping.shared()?.register(viewClass: TextViewEntryField.self, viewModelClass: TextViewEntryFieldModel.self)
// Buttons
MoleculeObjectMapping.shared()?.register(viewClass: PillButton.self, viewModelClass: ButtonModel.self)

View File

@ -9,7 +9,7 @@
import UIKit
@objc open class TextView: UITextView, UITextViewDelegate, MVMCoreViewProtocol {
@objc open class TextView: UITextView, UITextViewDelegate, MVMCoreViewProtocol, MoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -26,9 +26,21 @@ import UIKit
/// Set to true to hide the blinking textField cursor.
public var hideBlinkingCaret = false
public var textViewEntryFieldModel: TextViewEntryFieldModel? {
return model as? TextViewEntryFieldModel
public var textViewModel: TextViewModel? {
return model as? TextViewModel
}
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
if let color = model.backgroundColor?.uiColor {
backgroundColor = color
}
}
public var isEnabled: Bool = true {
didSet { }
}
/*
//--------------------------------------------------
// MARK: - Drawing Properties
@ -202,6 +214,7 @@ import UIKit
inputAccessoryView = nil
initialConfiguration()
}
/*
open override func layoutSubviews() {
super.layoutSubviews()
@ -368,8 +381,8 @@ import UIKit
isShowingPlaceholder = false
text = ""
font = textViewModel?.fontStyle.getFont()
textColor = textViewModel?.enabledTextColor.uiColor
font = Styler.Font.RegularBodySmall.getFont()//textViewModel?.fontStyle.getFont()
textColor = .black//textViewModel?.enabledTextColor.uiColor
}
public func setPlaceholderContentTraits() {
@ -397,7 +410,7 @@ import UIKit
@objc public func textViewDidBeginEditing(_ textView: UITextView) {
setTextAppearance()
isSelected = true
// isSelected = true
proprietorTextDelegate?.textViewDidBeginEditing?(textView)
}
@ -420,7 +433,7 @@ import UIKit
@objc public func textViewDidEndEditing(_ textView: UITextView) {
setPlaceholderIfAvailable()
isSelected = false
// isSelected = false
proprietorTextDelegate?.textViewDidEndEditing?(textView)
}
}

View File

@ -6,4 +6,87 @@
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import UIKit
open class TextViewModel: MoleculeModelProtocol {//, FormFieldProtocol, FormRuleWatcherFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String {
return ""
}
public var baseValue: AnyHashable?
public var backgroundColor: Color?
// public var fieldKey: String?
public var fontStyle: Styler.Font = Styler.Font.RegularBodySmall
public var text: String?
public var placeholder: String?
public var textAlignment: NSTextAlignment = .left
// public var groupName: String
public var editable: Bool = true
public var showsPlaceholder: Bool = false
public var placeholderTextColor: Color = Color(uiColor: .mvmCoolGray3)
public var placeholderFontStyle: Styler.Font = Styler.Font.RegularMicro
public var isValid: Bool? {
didSet { updateUI?() }
}
/// Temporary binding mechanism for the view to update on enable changes.
public var updateUI: ActionBlock?
//--------------------------------------------------
// MARK: - Validation Methods
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
return text
}
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
self.isValid = valid
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case editable
// case groupName
case textAlignment
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
if let editable = try typeContainer.decodeIfPresent(Bool.self, forKey: .editable) {
self.editable = editable
}
// if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
// self.groupName = groupName
// }
if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) {
self.textAlignment = textAlignment
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
// try container.encode(groupName, forKey: .groupName)
try container.encode(editable, forKey: .editable)
try container.encode(textAlignment, forKey: .textAlignment)
}
}