I'm trying to show the standard's number keyboard when the user gets to my ViewController
, and be able to capture user's input to fill some circles that are on the UI each time the user enters a number, the circles in question are the ones I show on this question.
How can I do that? All the question that I've already read suggest using UIKeyInput
protocol to display a custom keyboard, but that's not what I'm trying to do. One of those is this one.
The code I came up with, after checking the above post, was this one, but after a lot of reading and discussing, this was for having the above's UIView
as my custom keyboard and I'm unsure how to make it right.
ViewController
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var dotsView: DotsView!
var keyInputView: KeyInputView = KeyInputView()
override func viewDidLoad() {
super.viewDidLoad()
keyInputView.inputView = dotsView
keyInputView.becomeFirstResponder()
//self.view.addSubview(keyInputView) //In the XIB, the view is set to be displayed in center vertically and horizontally. If we uncomment this line, the view is pushed downwards.
}
}
DotsView
import UIKit
class DotsView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet var digitDots: [CircleView]!
//initWithFrame to init view from code
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
//initWithCode to init view from xib or storyboard
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
//common func to init our view
private func setupView() {
Bundle.main.loadNibNamed("DotsView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}
CircleView
import UIKit
@IBDesignable
class CircleView: UIView {
private var shapeLayer = CAShapeLayer()
@IBInspectable var fillColor: UIColor = .blue {
didSet {
shapeLayer.fillColor = fillColor.cgColor
}
}
override init(frame: CGRect = .zero) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
shapeLayer.fillColor = fillColor.cgColor
layer.addSublayer(shapeLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
}
}
KeyInputView
import UIKit
class KeyInputView: UIView {
var _inputView: UIView?
override var canBecomeFirstResponder: Bool { return true }
override var canResignFirstResponder: Bool { return true }
override var inputView: UIView? {
set { _inputView = newValue }
get { return _inputView }
}
}
// MARK: - UIKeyInput
//Modify if need more functionality
extension KeyInputView: UIKeyInput {
var hasText: Bool {
return false
}
func insertText(_ text: String) {
}
func deleteBackward() {
}
}
As for the XIBs you can access them in this repo
You probably want to make your DotsView
conform to UIKeyInput
...
class DotsView: UIView, UIKeyInput {
@IBOutlet var contentView: UIView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet var digitDots: [CircleView]!
//initWithFrame to init view from code
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
//initWithCode to init view from xib or storyboard
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
//common func to init our view
private func setupView() {
Bundle.main.loadNibNamed("DotsView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
var keyboardType: UIKeyboardType {
get {
return .numberPad
}
set {}
}
// required by UIKeyInput protocol
var hasText: Bool = false
override var canBecomeFirstResponder: Bool {
true
}
func insertText(_ text: String) {
print("Number tapped:", text)
// do something with the number that was tapped
}
func deleteBackward() {
print("Delete Backward tapped")
// do something because Delete was tapped
}
}
Then change your viewDidLoad()
in ViewController
to:
override func viewDidLoad() {
super.viewDidLoad()
dotsView.becomeFirstResponder()
}
Now, you have no need for an additional KeyInputView
.