效果图

自定义键盘的核心思想
- 设置UITextFiled 的InputView
- 切换键盘的思路为重新设置UITextFiled 的InputView然后再调用textFiled?.reloadInputViews()
*剩下的就是按键的布局与代理设置了
swift版本采用策略模式实现,Objc版本使用常规模式实现
- 策略模式请参看另一编文章https://blog.youkuaiyun.com/d06110902002/article/details/75642548
swift版本的策略模式实现的角色划分如下:
- 策略管理类–键盘管理类KeyboardMgr
- 通用策略类–键盘基类KeyboardBaseView
- 具体的策略类–数字键盘、随机数字键盘、英文键盘
##具体的源码如下:
import UIKit
class KeyboardMgr: UIView {
var keyboard : KeyboardBaseView?
static let shareInstace = KeyboardMgr()
lazy var keyboardInstanceDict : [String : KeyboardBaseView] = Dictionary()
func setInputMethodKeyboard(keyboardview keyboard : KeyboardBaseView,
inputView textfiled:UITextField,
onKeyClickListener listener:OnKeyListener) {
self.keyboard = keyboard
self.keyboard?.createView(inputView: textfiled, addOnClickListener: listener)
keyboardInstanceDict[keyboard.description] = keyboard
}
}
import UIKit
@objc protocol OnKeyListener {
@objc optional func onClick(button view:UIButton);
/// 文本观察监听接口
/// - Parameters:
/// - view: 被观察的对象
/// - bStr: 观察之前的文本
/// - cStr: 当前u文本
/// - aStr: 编辑之后最终的文本
@objc optional func addTextWatch(button view:UIButton,
beforeText bStr:String?,
curText cStr:String?,
afterText aStr:String?);
}
class KeyboardBaseView: UIView {
var textFiled : UITextField?
let DELETE : NSInteger = 19;
let FINISH : NSInteger = 21;
let ABC : NSInteger = 22;
let CAPTIAL : NSInteger = 23;
let SWITCH_TYPE : NSInteger = 24;
let SEARCH : NSInteger = 25;
let SPACE : NSInteger = 98;
var onClickListener : OnKeyListener?
lazy var beforeText : String = String.init()
lazy var curText : String = String.init()
lazy var afterText : String = String.init()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func createView(inputView targetView:UITextField,addOnClickListener listener:OnKeyListener){
self.textFiled = targetView;
targetView.inputView = self
self.onClickListener = listener
}
func createKey(titleTxt title:String,posX x:CGFloat, posY y:CGFloat, width w:CGFloat,hight h : CGFloat,forId id:NSInteger)->Void{
self.createKey(titleTxt: title, posX: x, posY: y, width: w, hight: h, forId: id, normalImg: nil, highLightimg: nil)
}
func createKey(titleTxt title:String,
posX x:CGFloat,
posY y:CGFloat,
width w:CGFloat,
hight h : CGFloat,
forId id:NSInteger,normalImg norBgImg:String?, highLightimg himg:String?)->Void{
let btnKey = UIButton();
btnKey.frame = CGRect.init(x: x, y: y, width: w, height: h);
self.addSubview(btnKey)
btnKey.tag = id
btnKey.setTitle(title, for: .normal)
btnKey.setTitleColor(UIColor.black, for: .normal)
btnKey.addTarget(self, action: #selector(onClickListener(button:)), for: .touchUpInside)
guard let nImg = norBgImg else{
btnKey.layer.cornerRadius = 5.0
return
}
btnKey.setBackgroundImage(UIImage.init(named: nImg), for: .normal)
guard let hImg = himg else{
return
}
btnKey.setBackgroundImage(UIImage.init(named: hImg), for: .highlighted)
}
@objc func onClickListener(button:UIButton) {
switch button.tag {
case (0...10),(100...126):
if self.onClickListener != nil {
self.onClickListener!.onClick?(button: button)
}
self.afterText.append(button.titleLabel!.text!)
break;
case ABC:
switchKeyboardType()
break;
case SEARCH:
break;
case SWITCH_TYPE:
switchKeyboardType()
break;
case CAPTIAL:
switchCaptial(button: button)
break;
case DELETE:
if !self.afterText.isEmpty{
let index = self.afterText.count - 1
self.afterText = self.afterText.prefix(index).description
}
break;
case FINISH:
hideKeyboard()
break;
default:
break;
}
if self.onClickListener != nil && !(21...30).contains(button.tag){
self.onClickListener?.addTextWatch?(button: button,
beforeText: self.beforeText,
curText: button.titleLabel!.text,
afterText: self.afterText)
self.beforeText = self.afterText;
}
}
func hideKeyboard() {
self.textFiled?.endEditing(true)
}
func switchCaptial(button view : UIButton) {
}
func switchKeyboardType() {
}
}
import UIKit
class NumberKeyboard: KeyboardBaseView {
lazy var logoLabel:UILabel = UILabel()
var colSpace : CGFloat = 5.0;
var rowSpace : CGFloat = 5.0
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.gray
createLogoView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func createView(inputView targetView: UITextField,addOnClickListener listener:OnKeyListener) {
super.createView(inputView: targetView,addOnClickListener: listener)
for view in self.subviews{
view.removeFromSuperview()
}
let width = (self.frame.size.width - self.colSpace * 4) / 3
let height = (self.frame.size.height - self.logoLabel.frame.size.height - self.rowSpace * 4 ) / 4
for i in 1..<10{
let indexColSpace = self.colSpace * CGFloat((i - 1) % 3)
let indexWidth = width * CGFloat((i - 1) % 3)
let x = self.colSpace + indexColSpace + indexWidth
let indexRowSpace = self.rowSpace * CGFloat((i - 1) / 3)
let indexRowHeight = height * CGFloat((i - 1) / 3)
let y = 44 + indexRowSpace + indexRowHeight
createKey(titleTxt: String.init(format: "%d", i),
posX: x,
posY: y,
width: width,
hight: height,
forId: i,
normalImg: "anniu1.png",
highLightimg: "anniu1_select.png")
}
createKey(titleTxt: "ABC",
posX: self.colSpace,
posY: self.logoLabel.frame.size.height + self.rowSpace * 3