系统自带的样式
- 在iOS开发中系统自带键盘已经有很多样式,但是有时候并不能满足我们都开发需求,需要或大或小的改动,这时候就需要我们自定义键盘了,系统自带键盘样式如下:
public enum UIKeyboardType : Int {
case `default` // Default type for the current input method.
case asciiCapable // Displays a keyboard which can enter ASCII characters
case numbersAndPunctuation // Numbers and assorted punctuation.
case URL // A type optimized for URL entry (shows . / .com prominently).
case numberPad // A number pad with locale-appropriate digits (0-9, ۰-۹, ०-९, etc.). Suitable for PIN entry.
case phonePad // A phone pad (1-9, *, 0, #, with letters under the numbers).
case namePhonePad // A type optimized for entering a person's name or phone number.
case emailAddress // A type optimized for multiple email address entry (shows space @ . prominently).
@available(iOS 4.1, *)
case decimalPad // A number pad with a decimal point.
@available(iOS 5.0, *)
case twitter // A type optimized for twitter text entry (easy access to @ #)
@available(iOS 7.0, *)
case webSearch // A default keyboard type with URL-oriented addition (shows space . prominently).
@available(iOS 10.0, *)
case asciiCapableNumberPad // A number pad (0-9) that will always be ASCII digits.
}
默认键盘效果图如下:
- 这里需要说明一下键盘收起的方法:
如果是单个输入框并且可以拿到该输入框想让键盘收起:textview.resignFirstResponder()
如果是很多输入输入框,不想一一判断哪个输入框是第一响应者,或者不好拿到输入框变量,键盘收起的方法有:view.endEditing(true)
如果想出发输入框为编辑状态,可以调用textview.becomeFirstResponder()
自定义键盘
- 有时候我们需要在原有的键盘上加一些控件,不需要改变原有键盘的布局,这时候只需要监听键盘的弹出和退出的通知,计算frame,然后在window上添加对应的控件即可。有时候系统自带键盘都没法满足我们都需求就需要完全自定义键盘了。
在系统自带键盘基础上自定义键盘
- 有时候我们只需要在现有的键盘上添加几个键,来组成自己想要的键盘如数字键盘没有收起键,可以添加一个收起键盘。
UITextField
和UITextView
有一个inputAccessoryView
的属性,当你想在键盘顶部展示一个自定义的view时,你就可以设置该属性。你设置的view就会自动和键盘keyboard一起显示了和隐藏。- 需要注意的是,你所自定义的view既不应该处在其他的视图层里,也不应该成为其他视图的子视图。其实也就是说,你所自定义的view只需要赋给属性
inputAccessoryView
就可以了,不要再做其他多余的操作。 - 监听键盘弹出和收起的4个通知,我们可以通过这些通知来获取键盘的frame,动画时间,动画轨迹等信息,可以做一些界面的调整,比如键盘掏出时挡住了输入框,要调整输入框的frame等。
NSNotificationName_OC/Swift | 对应的事件 |
---|---|
UIKeyboardWillShowNotification / UIKeyboardWillShow | 键盘将要弹出展示 |
UIKeyboardDidShowNotification / UIKeyboardDidShow | 键盘已经弹出展示 |
UIKeyboardWillHideNotification / UIKeyboardWillHide | 键盘将要收起隐藏 |
UIKeyboardDidHideNotification / UIKeyboardDidHide | 键盘已经收起隐藏 |
- 给数字键盘添加一个完成输入收起的按钮:
override func viewDidLoad() {
super.viewDidLoad()
// let topView = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 50))
// topView.barStyle = UIBarStyle.default
// topView.backgroundColor = UIColor.blue
let topView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 50))
topView.backgroundColor = UIColor.lightGray
let doneBtn = UIButton(type: UIButtonType.custom)
doneBtn.frame = CGRect(x: UIScreen.main.bounds.size.width - 80, y: 10, width: 60, height: 30)
doneBtn.setTitle("完成", for: UIControlState.normal)
doneBtn.layer.cornerRadius = 5
doneBtn.setTitleColor(UIColor.white, for: UIControlState.normal)
doneBtn.backgroundColor = UIColor.blue
doneBtn.addTarget(self, action: #selector(endEidt), for: UIControlEvents.touchUpInside)
topView.addSubview(doneBtn);
textField.inputAccessoryView = topView;
}
@objc func endEidt(){
view.endEditing(true)
}
注意:如果是用UIToolbar
通过addSubview
方式添加完成按钮,在iOS11中按钮的点击事件是无法响应的,因为图层问题。
完全自定义键盘
- 上面是在原有的键盘基础上添加一些自定义的视图,但是位置必须在原有键盘顶部,有一定的局限性。有时候我们需要改变键盘中键的位置标题等,如银行类app会有自定义安全键盘,身份证输入键盘等。(虽然身份证输入键盘可以在原有的基础上通过监听键盘的通知来添加和移出X按钮,但是会比较麻烦,完全自定义键盘反而更简单)。
UITextField
和UITextView
有一个inputView
的属性,inputView
就是显示键盘的view
,如果重写这个view
则不再弹出键盘,而是弹出自己的view。所以我们完全可以自定义任何我们想要展现的键盘。(通过该属性我们还可以做相应的从底部弹出来的弹框,只需要设置UITextField
和UITextView``inputView
的属性为弹框视图,UITextField
和UITextView
成为第一响应者则弹出,注销第一响应者则收起)。- 自定义一个数字安全键盘具体步骤如下:
- 自定键盘视图布局字控件
- 讲0~9数字随机排序并设置到键盘上展示
- 事件处理,0~9按键用于传值,每点击一下就拼接到
UITextField/UITextView
原有的text后面;删除建每点击一下就删除UITextField/UITextView
的text最后一个字符;完成按钮用于收起键盘,并在收起键盘后重新对键盘文字随机排序,设置到数字按键上,这样下次弹出键盘时就是又一套排序的数字安全键盘
- 具体如下:
自定义键盘:
import UIKit
//点击事件代理
@objc protocol CustomKeyboardDelegate: NSObjectProtocol {
@objc optional func keyboardItemDidClicked(_ item: String?)
@objc optional func deleteBtnClick()
@objc optional func doneBtnClick()
}
class CustomKeyboardView: UIView {
weak var delegate: CustomKeyboardDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
let shuffledIntegers = numberArr()
backgroundColor = UIColor.lightGray
//布局子空件
for index in 0..<12 {
let btn = UIButton(type: .custom)
btn.backgroundColor = UIColor.white
btn.addTarget(self, action: #selector(self.buttonDidClicked(_:)), for: .touchUpInside)
btn.frame = CGRect(x: self.frame.width / 3 * (CGFloat)(index % 3), y: (CGFloat)(45 * (index / 3)), width: self.frame.width / 3 - 1, height:44.0)
addSubview(btn)
btn.layer.borderWidth = 3
btn.layer.borderColor = UIColor.lightGray.cgColor
btn.layer.cornerRadius = 5
btn.tag = 100+index
btn.setTitleColor(UIColor.black, for: .normal)
if index == 10{
btn.setTitle("删除", for: .normal)
btn.setTitleColor(UIColor.red, for: .normal)
}else if index == 11{
btn.setTitle("完成", for: .normal)
btn.setTitleColor(UIColor.blue, for: .normal)
}else{
let indexString = "\(shuffledIntegers![index])"
btn.setTitle(indexString, for: .normal)
}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension CustomKeyboardView{
//随机排序0~9
func numberArr() -> [Any]? {
let startArray = NSMutableArray(array: [0,1,2,3,4,5,6,7,8,9])
let resultArray = NSMutableArray()
for i in 0..<startArray.count {
let t = arc4random() % UInt32(startArray.count)
resultArray[i] = startArray[Int(t)]
startArray[Int(t)] = startArray.lastObject as Any
startArray.removeLastObject()
}
return (resultArray as! [Any])
}
//点击事件
@objc func buttonDidClicked(_ sender: UIButton?) {
let index = sender!.tag - 100
if index < 10 {//传值
if (delegate != nil && (delegate?.responds(to: #selector(CustomKeyboardDelegate.keyboardItemDidClicked(_:))))!) {
delegate?.keyboardItemDidClicked!(sender?.titleLabel?.text)
}
}else if (index == 10){//删除
if (delegate != nil && (delegate?.responds(to: #selector(CustomKeyboardDelegate.deleteBtnClick)))!) {
delegate?.deleteBtnClick!()
}
}else{//收起键盘刷新键盘数字
if (delegate != nil && (delegate?.responds(to: #selector(CustomKeyboardDelegate.doneBtnClick)))!) {
delegate?.doneBtnClick!()
reloadKeyBoard()
}
}
}
//重新设置按钮标题
func reloadKeyBoard(){
let arr = (numberArr()as! Array<NSNumber>)
for index in 0..<arr.count {
let btn = (self.viewWithTag(Int(index)+100)) as!UIButton
let indexString = "\(arr[index])"
btn.setTitle(indexString, for: UIControlState.normal)
}
}
}
自定义键盘使用:
class CustomTwoViewController: UIViewController{
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let custimKB = CustomKeyboardView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 180+34))
custimKB.delegate = self as CustomKeyboardDelegate;
textField.inputView = custimKB;
textField.delegate = self as UITextFieldDelegate
}
}
//自定义键盘代理方法
extension CustomTwoViewController:CustomKeyboardDelegate,UITextFieldDelegate{
//拼接字符代理
func keyboardItemDidClicked(_ item: String?) {
textField.text = textField.text! + (item ?? "")
}
//删除字符代理
func deleteBtnClick(){
if textField.text != nil && (textField.text?.count)!>0 {
var str = textField.text!
//删除最后一个元素
str.removeLast()
textField.text = str
}
}
//完成安妞
func doneBtnClick(){
view.endEditing(true)
}
}
效果图如下:
- 注意:
这里支队iPhone X适配,对于其他机型还需要最额外的适配工作。
inputView
不会随着键盘出现而出现,设置了InputView
只会当UITextField
或者UITextView
变为第一相应者时显示出来, 不会显示键盘了。设置了InputAccessoryView,它会随着键盘一起出现并且会显示在键盘的顶端。InutAccessoryView默认为 nil.
自定义全部类型键盘
- 这里用完全自定义的方法写了个字母、数字、符号之间可以切换输入的键盘,并且进行了iPhoneX、XR、XS、XS Max等适配,效果如下:
相关源码:自定义全部类型键盘
自定义键盘demo
参考文档:
iOS自定义安全键盘