Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions AGInputControls/Source/FloatingLabelTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ open class FloatingLabelTextField : FormattingTextField {
}
}

/// shows in the placeholder the designation of a required field using " \*" with a color from errorColor. Default is `false`
public var isRequired: Bool = false {
didSet {
configureColors()
}
}

/// Colors placeholder label, bottom label and underline view in `tintColor` when textfield is focused. Default is `true`
open var highlightsWhenActive = true

Expand Down Expand Up @@ -143,6 +150,8 @@ open class FloatingLabelTextField : FormattingTextField {
textPadding.top + (font!.lineHeight * floatingLabelScaleFactor + floatingLabelBottomPadding)
}

private let requiredText: String = " *"

//MARK: - Init
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
Expand Down Expand Up @@ -211,8 +220,20 @@ open class FloatingLabelTextField : FormattingTextField {
}

private func configurePlaceholder() {
guard placeholder != nil else { return }
placeholderLabel.text = placeholder
guard let placeholder else { return }
if isRequired {
placeholderLabel.text = nil
let placeholderWithRequiredText = placeholder + requiredText
let mutableAttributedString = NSMutableAttributedString(
string: placeholderWithRequiredText,
attributes: [.foregroundColor: placeholderLabel.textColor])
let range = (placeholderWithRequiredText as NSString).range(of: requiredText)
mutableAttributedString.addAttribute(.foregroundColor, value: errorTintColor, range: range)
placeholderLabel.attributedText = mutableAttributedString
} else {
placeholderLabel.attributedText = nil
placeholderLabel.text = placeholder
}
placeholderLabel.sizeToFit()
}

Expand All @@ -232,6 +253,7 @@ open class FloatingLabelTextField : FormattingTextField {
}

placeholderLabel.textColor = color
configurePlaceholder()
underlineView.backgroundColor = color
bottomLabel.textColor = color
}
Expand Down
24 changes: 24 additions & 0 deletions Examples/FloatingLabelViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class StackViewController: UIViewController {
stackView.axis = .vertical
stackView.spacing = 1

let endEditingTap = UITapGestureRecognizer(target: self, action: #selector(tapView))
view.addGestureRecognizer(endEditingTap)

NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
Expand All @@ -41,6 +44,10 @@ class StackViewController: UIViewController {
// stackView.alignment = .leading
// }

@objc private func tapView() {
view.endEditing(true)
}

final class Entry: UIView {

let title: String
Expand Down Expand Up @@ -96,6 +103,7 @@ final class FloatingLabelViewController: StackViewController {

let floatTextField = FloatingLabelTextField()
let floatingFieldNoFormatting = FloatingLabelTextField()
let floatingFieldNoFormattingWithRequired = FloatingLabelTextField()
let floatingPhoneTextField = FloatingLabelTextField()

override func viewDidLoad() {
Expand All @@ -120,6 +128,15 @@ final class FloatingLabelViewController: StackViewController {
floatingFieldNoFormatting.leftView?.tintColor = .lightGray
floatingFieldNoFormatting.leftViewMode = .always

floatingFieldNoFormattingWithRequired.backgroundColor = UIColor.systemGreen.withAlphaComponent(0.15)
floatingFieldNoFormattingWithRequired.bottomText = "Bottom text"
floatingFieldNoFormattingWithRequired.placeholder = "Floating placeholder"
floatingFieldNoFormattingWithRequired.isRequired = true
floatingFieldNoFormattingWithRequired.showUnderlineView = true
floatingFieldNoFormattingWithRequired.highlightsWhenActive = true
floatingFieldNoFormattingWithRequired.clearButtonMode = .whileEditing
floatingFieldNoFormattingWithRequired.addTarget(self, action: #selector(didChangeNoFormattingWithRequired), for: .editingChanged)

floatTextField.placeholder = "Card number"
floatTextField.tintColor = .systemPurple
floatTextField.backgroundColor = .white
Expand All @@ -141,6 +158,8 @@ final class FloatingLabelViewController: StackViewController {

stackView.addArrangedSubview(Entry(title: "No formatting", targetView: floatingFieldNoFormatting))

stackView.addArrangedSubview(Entry(title: "No formatting with required", targetView: floatingFieldNoFormattingWithRequired))

stackView.addArrangedSubview(Entry(title: "Regular formatting", targetView: floatTextField))

stackView.addArrangedSubview(Entry(title: "Phone floating textfield", targetView: floatingPhoneTextField))
Expand All @@ -154,6 +173,11 @@ final class FloatingLabelViewController: StackViewController {
tf.isError = isError
}

@objc private func didChangeNoFormattingWithRequired(textField: UITextField) {
guard let tf = textField as? FloatingLabelTextField else { return }
tf.isError = tf.text!.count > 5
}

@objc func didTapClear() {
floatingFieldNoFormatting.text = nil
}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ FloatingLabelTextField is a `UITextField` subclass which resembles [Material des
floatTextField.formattingMask = "##/##" // Formatting mask
floatTextField.placeholder = "Expires at"
floatTextField.textPaddings = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0) // Paddings for text and floating placeholder
floatTextField.isRequired = true // Placeholder displays the required field symbol
floatTextField.highlightsWhenActive = true // Placeholder and underline view and bottom label are filled by tintColor when textfield is active

floatTextField.errorTintColor = .systemRed
Expand Down