New keyboard type for entering VIN

This commit is contained in:
Selim Mustafaev 2023-07-23 12:34:49 +03:00
parent 24e9b90c16
commit 2ef6968d00
5 changed files with 161 additions and 28 deletions

View File

@ -72,6 +72,21 @@
endingLineNumber = "37" endingLineNumber = "37"
offsetFromSymbolStart = "256"> offsetFromSymbolStart = "256">
</Location> </Location>
<Location
uuid = "2786565A-9610-4232-920E-0763816C4DBF - f20dc4504decd67d"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "Eureka.DatePickerRowProtocol.configurePickerStyle(Eureka.DatePickerCell, __C.UIDatePickerMode) -&gt; ()"
moduleName = "AutoCat"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/selim/Library/Developer/Xcode/DerivedData/AutoCat-fhilwnlnsrpirleiajogdcyhyyey/SourcePackages/checkouts/Eureka/Source/Rows/DateInlineRow.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "37"
endingLineNumber = "37"
offsetFromSymbolStart = "112">
</Location>
</Locations> </Locations>
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>

View File

@ -40,4 +40,21 @@ extension UIStackView {
self.distribution = distribution self.distribution = distribution
return self return self
} }
func removeAllArrangedSubviews() {
arrangedSubviews.forEach {
self.removeArrangedSubview($0)
NSLayoutConstraint.deactivate($0.constraints)
$0.removeFromSuperview()
}
}
func addArrangedSubviews(_ views: [UIView]) {
views.forEach { addArrangedSubview($0) }
}
func setArrangedSubviews(_ views: [UIView]) {
removeAllArrangedSubviews()
addArrangedSubviews(views)
}
} }

View File

@ -39,6 +39,7 @@ class NewNumberController: UIViewController {
private lazy var vinField: UITextField = { private lazy var vinField: UITextField = {
let view = UITextField() let view = UITextField()
view.translatesAutoresizingMaskIntoConstraints = false view.translatesAutoresizingMaskIntoConstraints = false
view.borderStyle = .roundedRect
view.isHidden = true view.isHidden = true
return view return view
}() }()
@ -48,6 +49,7 @@ class NewNumberController: UIViewController {
button.isEnabled = false button.isEnabled = false
button.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8) button.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8)
button.accessibilityIdentifier = "checkButton" button.accessibilityIdentifier = "checkButton"
button.setContentHuggingPriority(.defaultHigh, for: .horizontal)
return button return button
}() }()
@ -131,9 +133,13 @@ class NewNumberController: UIViewController {
case .plateNumber: case .plateNumber:
plateView.isHidden = false plateView.isHidden = false
vinField.isHidden = true vinField.isHidden = true
keyboardView.target = plateView
keyboardView.type = .plateNumber
case .vin: case .vin:
plateView.isHidden = true plateView.isHidden = true
vinField.isHidden = false vinField.isHidden = false
keyboardView.target = vinField
keyboardView.type = .vin
} }
} }
} }

View File

@ -15,28 +15,57 @@ enum PNButtonType {
case done case done
} }
enum PNKeyboardType {
case plateNumber
case vin
}
class PNButton: UIButton { class PNButton: UIButton {
private(set) var type: PNButtonType private(set) var type: PNButtonType
private var keyboardType: PNKeyboardType = .plateNumber
private var rectLayer = CAShapeLayer() private var rectLayer = CAShapeLayer()
private var bgColor = UIColor(named: "KeyBackground") private var bgColor = UIColor(named: "KeyBackground")
weak var delegate: PNButtonDelegate? weak var delegate: PNButtonDelegate?
init(letter: Character) { var letterFont: UIFont? {
switch keyboardType {
case .plateNumber:
return UIFont(name: "RoadNumbers", size: 36)
case .vin:
return .systemFont(ofSize: 24)
}
}
var digitFont: UIFont? {
switch keyboardType {
case .plateNumber:
return UIFont(name: "RoadNumbersCyr-Regular", size: 30)
case .vin:
return .systemFont(ofSize: 24)
}
}
init(letter: Character, keyboardType: PNKeyboardType = .plateNumber) {
self.type = .symbol(String(letter)) self.type = .symbol(String(letter))
self.keyboardType = keyboardType
super.init(frame: .zero) super.init(frame: .zero)
self.setup() self.setup()
self.titleLabel?.font = UIFont(name: "RoadNumbers", size: 36) self.titleLabel?.font = letterFont
let title = String(Constants.pnLettersMap[letter] ?? letter) let title = String(Constants.pnLettersMap[letter] ?? letter)
self.setTitle(title, for: .normal) self.setTitle(title, for: .normal)
self.setTitleColor(.label, for: .normal) self.setTitleColor(.label, for: .normal)
} }
init(digit: Int) { init(digit: Int, keyboardType: PNKeyboardType = .plateNumber) {
self.type = .symbol(String(digit)) self.type = .symbol(String(digit))
self.keyboardType = keyboardType
super.init(frame: .zero) super.init(frame: .zero)
self.setup() self.setup()
self.titleLabel?.font = UIFont(name: "RoadNumbersCyr-Regular", size: 30) self.titleLabel?.font = digitFont
let character = Character(String(digit)) let character = Character(String(digit))
let title = String(Constants.pnLettersMap[character] ?? character) let title = String(Constants.pnLettersMap[character] ?? character)
self.setTitle(title, for: .normal) self.setTitle(title, for: .normal)
@ -98,20 +127,52 @@ class PNButton: UIButton {
} }
class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate { class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate {
private weak var target: UIKeyInput? public weak var target: UIKeyInput?
weak var delegate: PNKeyboardDelegate? weak var delegate: PNKeyboardDelegate?
private let insets: UIEdgeInsets private let insets: UIEdgeInsets
init(target: UIKeyInput, insets: UIEdgeInsets = .zero) { public var type: PNKeyboardType {
didSet {
setupButtons()
}
}
var letters: [Character] {
switch type {
case .plateNumber:
return Array(Constants.pnLettersMap.keys)
case .vin:
return Constants.vinLetters
}
}
private var lettersWidthConstraint: NSLayoutConstraint?
private var digitsWidthConstraint: NSLayoutConstraint?
var mainStack: UIStackView = .horizontal([])
//.distribution(.fillProportionally)
.spacing(16)
init(target: UIKeyInput, type: PNKeyboardType = .plateNumber, insets: UIEdgeInsets = .zero) {
self.target = target self.target = target
self.insets = insets self.insets = insets
self.type = type
super.init(frame: .zero) super.init(frame: .zero)
self.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
let blurEffectView = UIVisualEffectView(effect: UIBlurEffect()) let blurEffectView = UIVisualEffectView(effect: UIBlurEffect())
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addSubview(blurEffectView) self.addSubview(blurEffectView)
self.addSubview(mainStack)
NSLayoutConstraint.activate([
mainStack.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: insets.left),
mainStack.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -insets.right),
mainStack.topAnchor.constraint(equalTo: self.topAnchor, constant: insets.top),
mainStack.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -insets.bottom)
])
self.setupButtons() self.setupButtons()
} }
@ -120,14 +181,53 @@ class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
override func layoutSubviews() {
super.layoutSubviews()
let lettersMult: CGFloat = type == .plateNumber ? 0.5 : 2.0/3.0
let digitsMult: CGFloat = type == .plateNumber ? 0.5 : 1.0/3.0
let availableWidth = frame.width - mainStack.spacing
let newLettersWidth = availableWidth*lettersMult
let newDigitsWidth = availableWidth*digitsMult
let needChangeConstraints = lettersWidthConstraint?.constant != newLettersWidth
|| digitsWidthConstraint?.constant != newDigitsWidth
if needChangeConstraints {
lettersWidthConstraint?.constant = newLettersWidth
digitsWidthConstraint?.constant = newDigitsWidth
}
}
func letterRows(from buttons: [PNButton]) -> [UIView] {
switch type {
case .plateNumber:
return [
createLetterStack([buttons[0], buttons[1], buttons[2]]),
createLetterStack([buttons[3], buttons[4], buttons[5]]),
createLetterStack([buttons[6], buttons[7], buttons[8]]),
createLetterStack([buttons[9], buttons[10], buttons[11]])
]
case .vin:
return [
createLetterStack([buttons[0], buttons[1], buttons[2], buttons[3], buttons[4], buttons[5]]),
createLetterStack([buttons[6], buttons[7], buttons[8], buttons[9], buttons[10], buttons[11]]),
createLetterStack([buttons[12], buttons[13], buttons[14], buttons[15], buttons[16], buttons[17]]),
createLetterStack([buttons[18], buttons[19], buttons[20], buttons[21], buttons[22]])
]
}
}
func setupButtons() { func setupButtons() {
let letters: [PNButton] = Constants.pnLettersMap.keys.sorted().map { letter in let letterButtons: [PNButton] = letters.sorted().map { letter in
let button = PNButton(letter: letter) let button = PNButton(letter: letter, keyboardType: type)
button.delegate = self button.delegate = self
return button return button
} }
let digits: [PNButton] = [1,2,3,4,5,6,7,8,9,0].map { digit in let digits: [PNButton] = [1,2,3,4,5,6,7,8,9,0].map { digit in
let button = PNButton(digit: digit) let button = PNButton(digit: digit, keyboardType: type)
button.delegate = self button.delegate = self
return button return button
} }
@ -139,14 +239,8 @@ class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate {
done.setBacgroundColor(color: .systemBlue) done.setBacgroundColor(color: .systemBlue)
done.tintColor = .white done.tintColor = .white
let letterRows = [ let rows = letterRows(from: letterButtons)
self.createLetterStack([letters[0], letters[1], letters[2]]), let lettersStack = UIStackView(arrangedSubviews: rows)
self.createLetterStack([letters[3], letters[4], letters[5]]),
self.createLetterStack([letters[6], letters[7], letters[8]]),
self.createLetterStack([letters[9], letters[10], letters[11]])
]
let lettersStack = UIStackView(arrangedSubviews: letterRows)
lettersStack.axis = .vertical lettersStack.axis = .vertical
lettersStack.distribution = .fillEqually lettersStack.distribution = .fillEqually
//lettersStack.spacing = 8 //lettersStack.spacing = 8
@ -163,18 +257,15 @@ class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate {
digitsStack.distribution = .fillEqually digitsStack.distribution = .fillEqually
//digitsStack.spacing = 8 //digitsStack.spacing = 8
let mainStack = UIStackView(arrangedSubviews: [lettersStack, digitsStack]) mainStack.setArrangedSubviews([lettersStack, digitsStack])
mainStack.spacing = 16
mainStack.distribution = .fillEqually
mainStack.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(mainStack)
NSLayoutConstraint.activate([ lettersWidthConstraint = lettersStack.widthAnchor.constraint(equalToConstant: 0)
mainStack.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: insets.left), digitsWidthConstraint = digitsStack.widthAnchor.constraint(equalToConstant: 0)
mainStack.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -insets.right),
mainStack.topAnchor.constraint(equalTo: self.topAnchor, constant: insets.top), lettersWidthConstraint?.priority = .defaultLow
mainStack.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -insets.bottom) digitsWidthConstraint?.priority = .defaultLow
])
NSLayoutConstraint.activate([lettersWidthConstraint, digitsWidthConstraint].compactMap { $0 })
} }
func createLetterStack(_ views: [UIView]) -> UIStackView { func createLetterStack(_ views: [UIView]) -> UIStackView {

View File

@ -15,6 +15,10 @@ public enum Constants {
"А": "A", "В": "B", "Е": "E", "К": "K", "М": "M", "Н": "H", "О": "O", "Р": "P", "С": "C", "Т": "T", "У": "Y", "Х": "X" "А": "A", "В": "B", "Е": "E", "К": "K", "М": "M", "Н": "H", "О": "O", "Р": "P", "С": "C", "Т": "T", "У": "Y", "Х": "X"
] ]
public static let vinLetters: [Character] = [
"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
]
public static let googleAuthURL = "https://accounts.google.com/o/oauth2/v2/auth" public static let googleAuthURL = "https://accounts.google.com/o/oauth2/v2/auth"
public static let googleTokenURL = "https://oauth2.googleapis.com/token" public static let googleTokenURL = "https://oauth2.googleapis.com/token"
public static let googleRedirectURL = "com.googleusercontent.apps.994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb:/oauth2callback" public static let googleRedirectURL = "com.googleusercontent.apps.994679674451-k7clunkk4nicl6iuajdtc5u7hvustbdb:/oauth2callback"