more.
This commit is contained in:
parent
88eec2bf9d
commit
6d7c1df7cc
@ -28,10 +28,10 @@ import UIKit
|
||||
private var previousSize: CGFloat = 0.0
|
||||
|
||||
/// Determines if a border should be drawn.
|
||||
private var hideBorder = false
|
||||
private var showError = false
|
||||
var hideBorder = false
|
||||
var showError = false
|
||||
|
||||
private var borderStrokeColor: UIColor = .mfSilver()
|
||||
var borderStrokeColor: UIColor = .mfSilver()
|
||||
private var borderPath: UIBezierPath = UIBezierPath()
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -10,40 +10,35 @@ import UIKit
|
||||
|
||||
/**
|
||||
* Subclass of TextEntryField due to the conveniences provided.
|
||||
* TODO: Compare overrides to determine if TextEntryField is necessary.
|
||||
*/
|
||||
@objcMembers open class DigitEntryField: TextEntryField, DigitBoxDelegate {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
public private(set) var digitFieldsView: UIView?
|
||||
public private(set) var digitFieldsStack: UIStackView?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
private var numberOfDigits = 4
|
||||
private(set) var numberOfDigits = 4
|
||||
private var switchedAutomatically = false
|
||||
|
||||
public var digitFields: [DigitBox] = []
|
||||
|
||||
public override var isEnabled: Bool {
|
||||
didSet {
|
||||
if isEnabled {
|
||||
titleLabel.textColor = .black
|
||||
} else {
|
||||
titleLabel.textColor = .mfBattleshipGrey()
|
||||
}
|
||||
titleLabel.textColor = isEnabled ? .black : .black
|
||||
|
||||
for textField in digitFields {
|
||||
textField.isUserInteractionEnabled = isEnabled
|
||||
textField.isEnabled = isEnabled
|
||||
textField.textColor = isEnabled ? .black : .mfBattleshipGrey()
|
||||
for digitBox in digitFields {
|
||||
digitBox.isUserInteractionEnabled = isEnabled
|
||||
digitBox.isEnabled = isEnabled
|
||||
digitBox.textColor = isEnabled ? .black : .mfBattleshipGrey()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets placeholder text in the textField.
|
||||
public override var placeholder: String? {
|
||||
get {
|
||||
var string = ""
|
||||
@ -85,6 +80,7 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
/// Traverses each digitbox to retrieve the held value.
|
||||
public override var text: String? {
|
||||
get {
|
||||
var string = ""
|
||||
@ -107,34 +103,48 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
public override var title: String? {
|
||||
get { return titleLabel.text }
|
||||
set {
|
||||
if let formText = newValue, !formText.isEmpty {
|
||||
titleContainerDistance?.constant = 10
|
||||
} else {
|
||||
titleContainerDistance?.constant = 0
|
||||
/// Updates the visual appearance of the container, with some logical laterations as well.
|
||||
public override func updateUI(appearance: Appearance) {
|
||||
|
||||
self.appearance = appearance
|
||||
isUserInteractionEnabled = true
|
||||
titleLabel.textColor = .mfBattleshipGrey()
|
||||
hideBorder = false
|
||||
feedback = showError ? errorMessage : nil
|
||||
|
||||
switch appearance {
|
||||
case .original:
|
||||
digitFields.forEach {
|
||||
$0.borderStrokeColor = .mfSilver()
|
||||
$0.bottomBar.backgroundColor = UIColor.black.cgColor
|
||||
}
|
||||
|
||||
super.title = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public override var errorMessage: String? {
|
||||
didSet {
|
||||
if let errorMessage = errorMessage, !errorMessage.isEmpty {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
if self.showError {
|
||||
self.feedbackContainerDistance?.constant = 10
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
self.digitFields.forEach { $0.showErrorState(true) }
|
||||
}
|
||||
case .error:
|
||||
digitFields.forEach {
|
||||
$0.borderStrokeColor = .mfPumpkin()
|
||||
$0.bottomBar.backgroundColor = UIColor.mfPumpkin().cgColor
|
||||
}
|
||||
self.digitFields.forEach { $0.showErrorState(true) }
|
||||
case .lock:
|
||||
digitFields.forEach {
|
||||
$0.isUserInteractionEnabled = false
|
||||
$0.hideBorder = true
|
||||
$0.bottomBar.backgroundColor = UIColor.clear.cgColor
|
||||
}
|
||||
case .select:
|
||||
digitFields.forEach {
|
||||
$0.borderStrokeColor = .black
|
||||
$0.bottomBar.backgroundColor = UIColor.black.cgColor
|
||||
}
|
||||
case .disable:
|
||||
digitFields.forEach {
|
||||
$0.isUserInteractionEnabled = false
|
||||
$0.borderStrokeColor = .mfSilver()
|
||||
$0.bottomBar.backgroundColor = self.isEnabled ? UIColor.black.cgColor : UIColor.mfSilver().cgColor
|
||||
}
|
||||
titleLabel.textColor = self.isEnabled ? .mfBattleshipGrey() : .mfSilver()
|
||||
}
|
||||
|
||||
refreshBorderUI(bottomBarSize: appearance == .error ? 4 : 1)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -158,7 +168,7 @@ import UIKit
|
||||
}
|
||||
|
||||
public init(numberOfDigits: Int, bothDelegates delegate: (UITextFieldDelegate & TextFieldDelegate)?, size: CGFloat? = nil) {
|
||||
super.init(bothDelegates: delegate as? (TextFieldDelegate & UITextFieldDelegate))
|
||||
super.init(bothDelegates: delegate)
|
||||
|
||||
setup()
|
||||
self.numberOfDigits = numberOfDigits
|
||||
@ -176,52 +186,18 @@ import UIKit
|
||||
|
||||
open func setup() {
|
||||
|
||||
// Border for Field Container will not be shown.
|
||||
hideBorder = true
|
||||
// titleLabel.styleB2(true)
|
||||
alignCenterHorizontal()
|
||||
isAccessibilityElement = false
|
||||
}
|
||||
|
||||
open override func setupFieldContainerContent(_ container: UIView) {
|
||||
|
||||
textField.removeFromSuperview()
|
||||
setupTextFieldsView(forSize: CGFloat(numberOfDigits))
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.titleLabel.updateView(size)
|
||||
|
||||
if !self.digitFields.isEmpty {
|
||||
|
||||
StackableViewController.remove(self.digitFields)
|
||||
|
||||
self.digitFields.forEach { $0.updateView(size) }
|
||||
}
|
||||
|
||||
// Layout text boxes.
|
||||
self.setupTextFieldsView(forSize: size)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
func removeError() {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.digitFields.forEach { $0.showErrorState(false) }
|
||||
}
|
||||
}
|
||||
|
||||
func createDigitField() -> DigitBox {
|
||||
|
||||
let textField = DigitBox()
|
||||
@ -237,7 +213,7 @@ import UIKit
|
||||
|
||||
// Remove all current UI.
|
||||
if !digitFields.isEmpty {
|
||||
StackableViewController.remove(digitFields)
|
||||
digitFieldsStack?.subviews.forEach { $0.removeFromSuperview() }
|
||||
}
|
||||
|
||||
if numberOfDigits > 0 {
|
||||
@ -258,6 +234,42 @@ import UIKit
|
||||
accessibilityElements = accessibleElements + [feedbackLabel]
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.titleLabel.updateView(size)
|
||||
|
||||
if !self.digitFields.isEmpty {
|
||||
|
||||
self.digitFieldsStack?.subviews.forEach { $0.removeFromSuperview() }
|
||||
self.digitFields.forEach { $0.updateView(size) }
|
||||
}
|
||||
|
||||
// Layout text boxes.
|
||||
self.setupTextFieldsView(forSize: size)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
func removeError() {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.digitFields.forEach { $0.showErrorState(false) }
|
||||
}
|
||||
}
|
||||
|
||||
override func valueChanged() {
|
||||
super.valueChanged()
|
||||
|
||||
@ -289,27 +301,13 @@ import UIKit
|
||||
|
||||
func setupTextFieldsView(forSize size: CGFloat) {
|
||||
|
||||
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize(),
|
||||
let digitFieldsView = digitFieldsView
|
||||
else { return }
|
||||
guard let space = MFSizeObject(standardSize: 5, smalliPhoneSize: 3)?.getValueBasedOnScreenSize() else { return }
|
||||
|
||||
StackableViewController.populateViewHorizontally(digitFieldsView, withUIArray: digitFields, withSpacingBlock: { object in
|
||||
|
||||
var inset = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space)
|
||||
|
||||
if self.digitFields.count == 1 {
|
||||
inset.left = 0
|
||||
inset.right = 0
|
||||
|
||||
} else if let field = object as? UITextField, field == self.digitFields.first {
|
||||
inset.left = 0
|
||||
|
||||
} else if let field = object as? UITextField, field == self.digitFields.last {
|
||||
inset.right = 0
|
||||
}
|
||||
|
||||
return inset
|
||||
})
|
||||
let stack = UIStackView(arrangedSubviews: digitFields)
|
||||
self.digitFieldsStack = stack
|
||||
textField.addSubview(stack)
|
||||
stack.distribution = .equalSpacing
|
||||
stack.spacing = space
|
||||
}
|
||||
|
||||
public override func defaultValidationBlock() {
|
||||
@ -367,6 +365,7 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
|
||||
guard let dictionary = json else { return }
|
||||
|
||||
@ -382,25 +381,12 @@ import UIKit
|
||||
}
|
||||
|
||||
buildTextFieldsView(size: MVMCoreUIUtility.getWidth())
|
||||
|
||||
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Accessibility
|
||||
//--------------------------------------------------
|
||||
|
||||
open override class func accessibilityElements() -> [Any]? {
|
||||
// let fields = []
|
||||
|
||||
// return self.digitFields
|
||||
return nil
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Text Field Delegate
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -73,7 +73,7 @@ import UIKit
|
||||
return layer
|
||||
}()
|
||||
|
||||
public private(set) var appearance: Appearance = .original
|
||||
public var appearance: Appearance = .original
|
||||
|
||||
public var showError = false
|
||||
|
||||
|
||||
@ -160,6 +160,7 @@
|
||||
strokeColor = .black
|
||||
}
|
||||
|
||||
/// Ensure you have defined a CaretSize with Orientation before calling.
|
||||
@objc public func setConstraints() {
|
||||
|
||||
guard let dimensions = size?.dimensions() else { return }
|
||||
|
||||
@ -23,6 +23,7 @@ import UIKit
|
||||
// For separation between cells.
|
||||
public var topSeparatorView: SeparatorView?
|
||||
public var bottomSeparatorView: SeparatorView?
|
||||
|
||||
public enum SeparatorFrequency: String {
|
||||
case all
|
||||
case allExceptTop
|
||||
@ -40,17 +41,21 @@ import UIKit
|
||||
|
||||
// MARK: - Styling
|
||||
open func style(with styleString: String?) {
|
||||
guard let styleString = styleString else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let styleString = styleString else { return }
|
||||
|
||||
switch styleString {
|
||||
case "standard":
|
||||
styleStandard()
|
||||
|
||||
case "header":
|
||||
styleHeader()
|
||||
|
||||
case "none":
|
||||
styleNone()
|
||||
default: break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,13 +209,18 @@ import UIKit
|
||||
// MARK: - Arrow
|
||||
/// Adds the standard mvm style caret to the accessory view
|
||||
@objc public func addCaretViewAccessory() {
|
||||
|
||||
guard accessoryView == nil else { return }
|
||||
let width: CGFloat = 6
|
||||
let height: CGFloat = 10
|
||||
|
||||
caretView = CaretView(lineWidth: 1)
|
||||
caretView?.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
caretViewWidthSizeObject = MFSizeObject(standardSize: width, standardiPadPortraitSize: 9)
|
||||
caretViewHeightSizeObject = MFSizeObject(standardSize: height, standardiPadPortraitSize: 16)
|
||||
caretView?.size = .small(.vertical)
|
||||
caretView?.setConstraints()
|
||||
|
||||
if let size = caretView?.size?.dimensions() {
|
||||
caretViewWidthSizeObject = MFSizeObject(standardSize: size.width, standardiPadPortraitSize: 9)
|
||||
caretViewHeightSizeObject = MFSizeObject(standardSize: size.height, standardiPadPortraitSize: 16)
|
||||
}
|
||||
|
||||
accessoryView = caretView
|
||||
}
|
||||
|
||||
@ -258,7 +268,7 @@ import UIKit
|
||||
} else {
|
||||
topSeparatorView?.hide()
|
||||
bottomSeparatorView?.setAsLight()
|
||||
setSeparatorFrequency(TableViewCell.SeparatorFrequency.allExceptTop, indexPath: indexPath)
|
||||
setSeparatorFrequency(.allExceptTop, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user