因為項目又一個提現的功能,textfiled文本框輸入需要彈出數字鍵盤,首先想到的就是設置textfiled的keyboardType為numberPad,此時你會看到如下的效果:

但是很遺憾這樣設置雖然出現了數字鍵盤,但是對於我們提現的這個功能來說是需要小數的,所以需要一個小數點 但是使用上面的鍵盤顯然不能滿足我們的需求,那么應該如何解決這樣的問題呢? 想了一下,有兩個方法取實現:
1.自定義一個鍵盤視圖
2.在系統鍵盤的基礎上修改
經過思考,自定義鍵盤代價太大,所以我才用了第二種方法。
為了在系統鍵盤基礎上修改,首先我們需要拿到鍵盤,那么如何拿到呢?我們知道鍵盤也是一個window, 所以最簡單的方式就是打印出當前視圖上面的window,拿到鍵盤所屬的window,然后遍歷內部的子控件即可 但是我沒有直接取打印,我直接通過程序的調用棧就可以看到當前鍵盤所屬的window及其內部的子控件,以下是我通過程序調用棧看到的結果:
![]()
可以看到鍵盤是一個名字叫UIRemoteKeyboardWindow的window 管理的,然后通過上圖可以看到真正鍵盤輸入視圖應該是叫UIInputSetHostView,真正的鍵盤面板的父視圖是一個叫UIKBKeyplaneView的view ,我們可以看到UIKBKeyplaneView李 main的第一個子控件是一個叫UIKBSplitImageView 這個就是底部的刪除按鈕(暫且我們就叫里面的每一個控件為按鈕吧)剩余的都對應於 1 2 3 4 5 6 7 8 9 0 這幾個控件 都是UIKBKeyView類型的。
通過上面的分析之后,我們就很好做了,我們只需要拿到鍵盤面板視圖 在它上面添加一個小數點按鈕 即可。注意如果添加子控件需要響應事件,必須添加到UIKBKeyplaneView這個視圖上面,否則添加的子控件將無法響應事件。
通過上面分析我們就很好下手了, 所以接下來我們上代碼:
第一步自定義一個小數點按鈕:
/// 自定義鍵盤小數點按鈕 lazyvarpointBtn:UIButton= { letpointBtn = UIButton() pointBtn.frame = CGRect(x:0, y:162, width:106, height:54) pointBtn.setTitle(".", for: .normal) pointBtn.tag =0xffbb33 pointBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize:35) pointBtn.setTitleColor(UIColor.black, for: .normal) pointBtn.addTarget(self, action:#selector(pointBtnClick), for: .touchUpInside) return pointBtn }()
然后我們需要監聽鍵盤將要顯示的通知,在鍵盤將要顯示的時候添加我們自己的按鈕,我們在控制器里實現如下代碼:
//監聽鍵盤彈出
NotificationCenter.default.addObserver(self, selector:#selector(keyBoardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object:nil)
然后實現監聽方法:
//鍵盤的出現
func keyBoardWillShow(_notification:Notification){
addPointBtn()
}
/// 添加小數點按鈕 func addPointBtn(){ var foundKeyboard:UIView? var keyboardWindow:UIWindow? for testWindow in UIApplication.shared.windows { if testWindow.description.hasPrefix("<UIRemoteKeyboardWindow") { keyboardWindow = testWindow break } } if (keyboardWindow == nil) {return} for possibleKeyboard in keyboardWindow!.subviews { MyLog(message: "keyboardWindow==\(possibleKeyboard)") if possibleKeyboard.description.hasPrefix("<UIInputSetContainerView") { MyLog(message: "possibleKeyboard==\(possibleKeyboard)") for possibleKeyboard_2 in possibleKeyboard.subviews { MyLog(message: "possibleKeyboard_2==\(possibleKeyboard_2)") if possibleKeyboard_2.description.hasPrefix("<UIInputSetHostView") { //查找鍵盤面板視圖 foundKeyboard = findInputPlaneView(superView: possibleKeyboard_2) //添加按鈕 if (foundKeyboard != nil) { //如果沒有添加過小數點按鈕就添加 // if (foundKeyboard!.viewWithTag(0xffbb33) == nil) { foundKeyboard!.addSubview(pointBtn) MyLog(message: "添加小數點按鈕") // } } return } } } } } /// 查找鍵盤的面板視圖 func findInputPlaneView(superView:UIView)->UIView?{ var planeView:UIView? for subview in superView.subviews { if subview.description.hasPrefix("<UIKBKeyplaneView") { MyLog(message: "找到鍵盤面板") return subview }else{ planeView = findInputPlaneView(superView: subview) } } return planeView }
最后我們再實現小數點按鈕點擊的事件即可:
/// 小數點按鈕的點擊 func pointBtnClick(){ //如果沒有輸入內容 直接退出 if textField.text == nil || textField.text == "" { return } //判斷是否已經輸入了小數點 if !textField.text!.contains(".") { //如果沒有輸入小數點就添加小數點到當前內容的末尾 let oldStrin = textField.text!.appending(".") textField.text = oldStrin } MyLog(message: "pointBtnClickpointBtnClickpointBtnClickpointBtnClick") }
然后運行項目之后,你會發現鍵盤左下角就添加了我們自己的小數點按鈕了。

小數點按鈕的位置是通過計算的,通過打印我發現了鍵盤的高度為216 ,鍵盤寬度肯定是屏幕的寬度,然后每行每列顯示的視圖個數固定,想想你知道如何算的。
現在我們的小數點就可以輸入了,接下來最后一步限制用戶只能輸入小數點后面兩位,
實現textfield的代理方法
//限制只能輸入金額 functextField(_textField:UITextField, shouldChangeCharactersIn range:NSRange, replacementString string:String) ->Bool{ letnewString = (textField.text!asNSString).replacingCharacters(in: range, with: string) letexpression ="^[0-9]*((\\.)[0-9]{0,2})?$" letregex =try! NSRegularExpression(pattern: expression, options: NSRegularExpression.Options.allowCommentsAndWhitespace) letnumberOfMatches = regex.numberOfMatches(in: newString, options:NSRegularExpression.MatchingOptions.reportProgress, range: NSMakeRange(0, (newStringasNSString).length)) return numberOfMatches !=0 }
到此基本就完成了我們想要的效果了