Issue #347
Add a hidden UITextField
to view hierarchy, and add UITapGestureRecognizer
to activate that textField.
Use padding string with limit to the number of labels, and prefix to get exactly n characters.
DigitView.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| import UIKit
final class DigitView: UIView { lazy var stackView: UIStackView = { let view = UIStackView() view.axis = .horizontal view.distribution = .equalSpacing return view }()
private(set) var boxes: [UIView] = [] private(set) var labels: [UILabel] = []
lazy var hiddenTextField: UITextField = { let textField = UITextField() textField.alpha = 0 textField.keyboardType = .numbersAndPunctuation return textField }()
lazy var tapGR = UITapGestureRecognizer(target: self, action: #selector(handle(_:)))
override init(frame: CGRect) { super.init(frame: frame) setup()
addGestureRecognizer(tapGR) }
required init?(coder aDecoder: NSCoder) { fatalError() }
override func layoutSubviews() { super.layoutSubviews()
boxes.forEach { $0.layer.borderWidth = 1 $0.layer.borderColor = R.color.primary.cgColor $0.layoutIfNeeded() $0.layer.cornerRadius = $0.bounds.height / 2 } }
@objc private func handle(_ tapGR: UITapGestureRecognizer) { hiddenTextField.becomeFirstResponder() }
private func setup() { addSubviews([hiddenTextField, stackView]) boxes = Array(0..<6).map { _ in return UIView() }
labels = boxes.map { box in let label = UILabel() label.font = R.customFont.semibold(16) label.textAlignment = .center label.textColor = R.color.primary box.addSubview(label)
NSLayoutConstraint.on([ label.centerXAnchor.constraint(equalTo: box.centerXAnchor), label.centerYAnchor.constraint(equalTo: box.centerYAnchor) ])
return label }
boxes.forEach { stackView.addArrangedSubview($0)
NSLayoutConstraint.on([ $0.heightAnchor.constraint(equalTo: stackView.heightAnchor, multiplier: 0.9), $0.widthAnchor.constraint(equalTo: $0.heightAnchor, multiplier: 1.0) ]) }
NSLayoutConstraint.on([ stackView.pinEdges(view: self, inset: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: -16)) ]) } }
|
DigitHandler.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| final class DigitHandler: NSObject { let digitView: DigitView
init(digitView: DigitView) { self.digitView = digitView super.init()
digitView.hiddenTextField.delegate = self digitView.hiddenTextField.addTarget(self, action: #selector(handle(_:)), for: .editingChanged) }
@objc private func handle(_ textField: UITextField) { guard let text = textField.text else { return }
let count = digitView.labels.count let paddedText = String(text.padding(toLength: count, withPad: "-", startingAt: 0).prefix(count)) zip(digitView.labels, paddedText).forEach { tuple in tuple.0.text = String(tuple.1) } } }
extension DigitHandler: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true }
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let text = textField.text ?? "" return text.count < digitView.labels.count } }
|