Finished basic variant of "check new number" puller
This commit is contained in:
parent
d34237ecf9
commit
1c12fe5b40
@ -9,11 +9,16 @@
|
|||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>AutoCatCore.xcscheme_^#shared#^_</key>
|
<key>AutoCat2.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>AutoCatCore.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "1.000",
|
"blue" : "0xFF",
|
||||||
"green" : "1.000",
|
"green" : "0xFF",
|
||||||
"red" : "1.000"
|
"red" : "0xFF"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "1.000",
|
||||||
|
"green" : "1.000",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.152",
|
||||||
|
"green" : "0.152",
|
||||||
|
"red" : "0.152"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.000",
|
||||||
|
"green" : "0.000",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.182",
|
||||||
|
"green" : "0.225",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.000",
|
||||||
|
"green" : "0.000",
|
||||||
|
"red" : "0.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.866",
|
||||||
|
"green" : "0.866",
|
||||||
|
"red" : "0.866"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -33,6 +33,8 @@ class PlateView: UIView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var onChange: (() -> Void)?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
setup()
|
setup()
|
||||||
@ -81,6 +83,7 @@ class PlateView: UIView {
|
|||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
guard let number = self.number else { return }
|
guard let number = self.number else { return }
|
||||||
guard let fgColorMain = UIColor(named: "PlateForeground")?.cgColor else { return }
|
guard let fgColorMain = UIColor(named: "PlateForeground")?.cgColor else { return }
|
||||||
guard let bgColor = UIColor(named: "PlateBackground")?.cgColor else { return }
|
guard let bgColor = UIColor(named: "PlateBackground")?.cgColor else { return }
|
||||||
@ -134,16 +137,26 @@ class PlateView: UIView {
|
|||||||
let height = fontSize/1.1 + 4
|
let height = fontSize/1.1 + 4
|
||||||
let width = height/PlateView.aspectRatio
|
let width = height/PlateView.aspectRatio
|
||||||
return CGSize(width: width, height: height)
|
return CGSize(width: width, height: height)
|
||||||
|
|
||||||
// guard self.bounds.width != 0 || self.bounds.height != 0 else {
|
|
||||||
// return CGSize.zero
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// let curAspectRatio = self.bounds.height/self.bounds.width
|
|
||||||
// if curAspectRatio >= PlateView.aspectRatio {
|
|
||||||
// return CGSize(width: self.bounds.width, height: self.bounds.width*PlateView.aspectRatio)
|
|
||||||
// } else {
|
|
||||||
// return CGSize(width: self.bounds.height/PlateView.aspectRatio, height: self.bounds.height)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension PlateView: UIKeyInput {
|
||||||
|
|
||||||
|
var hasText: Bool {
|
||||||
|
number?.hasText ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
func insertText(_ text: String) {
|
||||||
|
if number?.insertText(text) == true {
|
||||||
|
layoutSubviews()
|
||||||
|
onChange?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteBackward() {
|
||||||
|
if number?.deleteBackward() == true {
|
||||||
|
layoutSubviews()
|
||||||
|
onChange?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -6,32 +6,33 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import AutoCatCore
|
||||||
|
|
||||||
class CheckController: UIViewController {
|
class CheckController: UIViewController {
|
||||||
|
|
||||||
public var onCheck: ((String) -> Void)?
|
public var onCheck: ((String) -> Void)?
|
||||||
|
|
||||||
private lazy var keyboardView: PNKeyboard = {
|
private lazy var keyboardView: PNKeyboard = {
|
||||||
let keyboard = PNKeyboard(target: self.numberField, insets: .zero)
|
let keyboard = PNKeyboard(target: self.plateView, insets: .zero)
|
||||||
keyboard.delegate = self
|
keyboard.delegate = self
|
||||||
return keyboard
|
return keyboard
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var numberField: SwiftMaskTextfield = {
|
private lazy var plateView: PlateView = {
|
||||||
let textField = SwiftMaskTextfield()
|
let view = PlateView(frame: .zero)
|
||||||
textField.formatPattern = "@###@@###"
|
view.fontSize = 48
|
||||||
textField.placeholder = "A001AA 777"
|
view.number = PlateNumber("")
|
||||||
textField.borderStyle = .roundedRect
|
view.onChange = onNumberChanged
|
||||||
textField.font = .preferredFont(forTextStyle: .largeTitle)
|
view.setContentHuggingPriority(.defaultHigh, for: .horizontal)
|
||||||
textField.textAlignment = .center
|
return view
|
||||||
textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
|
|
||||||
return textField
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private let plateView = PlateView(frame: .zero)
|
private lazy var checkButton: ACButton = {
|
||||||
|
let button = ACButton(title: "Check", onTap: check)
|
||||||
private lazy var checkButton = ACButton(title: "Check", onTap: check)
|
button.isEnabled = false
|
||||||
.enable(false)
|
button.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
private lazy var stackView: UIStackView = {
|
private lazy var stackView: UIStackView = {
|
||||||
let stack = UIStackView(arrangedSubviews: [plateView, checkButton])
|
let stack = UIStackView(arrangedSubviews: [plateView, checkButton])
|
||||||
@ -43,7 +44,7 @@ class CheckController: UIViewController {
|
|||||||
|
|
||||||
private let titleLabel: UILabel = {
|
private let titleLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "Check new plate number"
|
label.text = "Check new number"
|
||||||
label.font = UIFont.preferredFont(forTextStyle: .headline)
|
label.font = UIFont.preferredFont(forTextStyle: .headline)
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
label.translatesAutoresizingMaskIntoConstraints = false
|
label.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@ -61,34 +62,22 @@ class CheckController: UIViewController {
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
//view.backgroundColor = .systemBackground
|
|
||||||
checkButton.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8)
|
|
||||||
|
|
||||||
view.addSubview(mainStackView)
|
view.addSubview(mainStackView)
|
||||||
mainStackView.pin(to: view, insets: .init(top: 16, left: 16, bottom: 16, right: 16))
|
mainStackView.pin(to: view, insets: .init(top: 16, left: 16, bottom: 16, right: 16))
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
plateView.heightAnchor.constraint(equalToConstant: 40)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
|
||||||
super.viewDidAppear(animated)
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
||||||
self.numberField.becomeFirstResponder()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func check() {
|
func check() {
|
||||||
guard let number = numberField.text else {
|
guard let number = plateView.number, number.isValid else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let numberNormalized = number.filter { !$0.isWhitespace }.uppercased()
|
let numberNormalized = number.asString().filter { !$0.isWhitespace }.uppercased()
|
||||||
numberField.resignFirstResponder()
|
|
||||||
onCheck?(numberNormalized)
|
onCheck?(numberNormalized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func onNumberChanged() {
|
||||||
|
checkButton.isEnabled = plateView.number?.isValid ?? false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CheckController: PNKeyboardDelegate {
|
extension CheckController: PNKeyboardDelegate {
|
||||||
@ -97,16 +86,3 @@ extension CheckController: PNKeyboardDelegate {
|
|||||||
check()
|
check()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension CheckController: UITextFieldDelegate {
|
|
||||||
|
|
||||||
@objc func textFieldDidChange(_ textField: UITextField) {
|
|
||||||
guard let text = textField.text else {
|
|
||||||
self.checkButton.isEnabled = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.checkButton.isEnabled = text.count >= 8
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -41,13 +41,13 @@ class MainTabController: UITabBarController, UITabBarControllerDelegate {
|
|||||||
func showCheckPuller() {
|
func showCheckPuller() {
|
||||||
var attributes = EKAttributes.bottomToast
|
var attributes = EKAttributes.bottomToast
|
||||||
attributes.displayDuration = .infinity
|
attributes.displayDuration = .infinity
|
||||||
attributes.positionConstraints.keyboardRelation = .bind(offset: .none)
|
attributes.entryBackground = .visualEffect(style: .extra) //.color(color: .standardBackground)
|
||||||
attributes.entryBackground = .color(color: .standardBackground)
|
attributes.screenBackground = .color(color: EKColor(UIColor(white: 0, alpha: 0.7)))
|
||||||
attributes.screenBackground = .color(color: EKColor(UIColor(white: 0.3, alpha: 0.5)))
|
|
||||||
attributes.roundCorners = .top(radius: 24)
|
attributes.roundCorners = .top(radius: 24)
|
||||||
attributes.screenInteraction = .dismiss
|
attributes.screenInteraction = .dismiss
|
||||||
attributes.entryInteraction = .forward
|
attributes.entryInteraction = .forward
|
||||||
//attributes.shadow = .active(with: .init(color: .black, opacity: 0.2, radius: 24, offset: .zero))
|
attributes.entranceAnimation = .init(translate: .init(duration: 0.2))
|
||||||
|
attributes.exitAnimation = .init(translate: .init(duration: 0.2))
|
||||||
|
|
||||||
let checkController = CheckController()
|
let checkController = CheckController()
|
||||||
checkController.onCheck = { number in
|
checkController.onCheck = { number in
|
||||||
|
|||||||
@ -1,11 +1,19 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class PlateNumber {
|
public class PlateNumber {
|
||||||
private var number: String
|
private var number: String = ""
|
||||||
private var numberEnglish: String
|
private var numberEnglish: String = ""
|
||||||
|
|
||||||
|
private let maxLength = 9
|
||||||
|
private let mainPartLength = 6
|
||||||
|
private let isDigitMask = [false, true, true, true, false, false, true, true, true]
|
||||||
|
|
||||||
public init(_ string: String) {
|
public init(_ string: String) {
|
||||||
self.number = string
|
setNumber(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func setNumber(_ number: String) {
|
||||||
|
self.number = number
|
||||||
self.numberEnglish = String(self.number.map { Constants.pnLettersMap[$0] ?? $0 })
|
self.numberEnglish = String(self.number.map { Constants.pnLettersMap[$0] ?? $0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,12 +22,47 @@ public class PlateNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func mainPart() -> String {
|
public func mainPart() -> String {
|
||||||
let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6)
|
return String(self.numberEnglish.prefix(mainPartLength))
|
||||||
return String(self.numberEnglish[..<index])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func region() -> String {
|
public func region() -> String {
|
||||||
let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6)
|
guard numberEnglish.count > mainPartLength else {
|
||||||
return String(self.numberEnglish[index...])
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(self.numberEnglish.dropFirst(mainPartLength))
|
||||||
|
}
|
||||||
|
|
||||||
|
public var isValid: Bool {
|
||||||
|
number.count >= 8
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UIKeyInput
|
||||||
|
|
||||||
|
public var hasText: Bool {
|
||||||
|
return !number.isEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if number was changed
|
||||||
|
public func insertText(_ text: String) -> Bool {
|
||||||
|
guard number.count < maxLength, text.count == 1 else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if text.first?.isNumber == isDigitMask[number.count] {
|
||||||
|
setNumber(number + text)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func deleteBackward() -> Bool {
|
||||||
|
guard !number.isEmpty else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
setNumber(String(number.dropLast()))
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user