IOS自定義鍵盤(pán)

效果圖

QQ20200527-152722-HD.gif

自定義鍵盤(pán)的核心思想

  • 設(shè)置UITextFiled 的InputView
  • 切換鍵盤(pán)的思路為重新設(shè)置UITextFiled 的InputView然后再調(diào)用textFiled?.reloadInputViews()
    *剩下的就是按鍵的布局與代理設(shè)置了

swift版本采用策略模式實(shí)現(xiàn)瞬哼,Objc版本使用常規(guī)模式實(shí)現(xiàn)

swift版本的策略模式實(shí)現(xiàn)的角色劃分如下:

  • 策略管理類(lèi)--鍵盤(pán)管理類(lèi)KeyboardMgr
  • 通用策略類(lèi)--鍵盤(pán)基類(lèi)KeyboardBaseView
  • 具體的策略類(lèi)--數(shù)字鍵盤(pán)蜂桶、隨機(jī)數(shù)字鍵盤(pán)抖锥、英文鍵盤(pán)

具體的源碼如下:

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
    }

}

  • 策略基類(lèi)源碼:
import UIKit

@objc protocol OnKeyListener {
    @objc optional func onClick(button view:UIButton);
    
    
    /// 文本觀(guān)察監(jiān)聽(tīng)接口
    /// - Parameters:
    ///   - view: 被觀(guān)察的對(duì)象
    ///   - bStr: 觀(guān)察之前的文本
    ///   - cStr: 當(dāng)前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() {
        
    }


}

  • 數(shù)字鍵盤(pán)類(lèi)
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 + height * 3,
                             width: width,
                             hight: height,
                             forId: ABC,
                             normalImg: "anniu1.png",
                             highLightimg: "anniu1_select.png")
        
        createKey(titleTxt: String.init(format: "%d", 0),
                        posX: self.colSpace * 2 + width,
                        posY: self.logoLabel.frame.size.height + self.rowSpace * 3 + height * 3,
                        width: width,
                        hight: height,
                        forId: 0,
                        normalImg: "anniu1.png",
                        highLightimg: "anniu1_select.png")
        
        createKey(titleTxt: "X",
                        posX: self.colSpace * 3 + width * 2,
                        posY: self.logoLabel.frame.size.height + self.rowSpace * 3 + height * 3,
                        width: width,
                        hight: height,
                        forId: DELETE,
                        normalImg: "anniu1.png",
                        highLightimg: "anniu1_select.png")
        
        
    }
    
    func createLogoView(){
        self.logoLabel.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: 44)
        self.addSubview(self.logoLabel)
        self.logoLabel.text = "硬漢安全鍵盤(pán)"
        self.logoLabel.textAlignment = .center
        logoLabel.font = UIFont.systemFont(ofSize: 14)
        logoLabel.textColor = UIColor.white
        
        let btnFinish = UIButton.init()
        btnFinish.frame = CGRect.init(x: self.frame.size.width - 100, y: 0, width: 100, height: 44)
        self.addSubview(btnFinish)
        btnFinish.tag = FINISH
        btnFinish.setTitle("完成", for: .normal)
        btnFinish.setTitleColor(UIColor.blue, for: .normal)
        btnFinish.addTarget(self, action: #selector(onClickListener(button:)), for:.touchUpInside)
        
    }
    
    override func switchKeyboardType() {
        var abcKeyboard = KeyboardMgr.shareInstace.keyboardInstanceDict[AbcKeyboard.self.description()]
               
       if(abcKeyboard == nil){
           abcKeyboard = AbcKeyboard.init(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 260))
           KeyboardMgr.shareInstace.keyboardInstanceDict[AbcKeyboard.self.description()] = abcKeyboard
       }
       KeyboardMgr.shareInstace.setInputMethodKeyboard(keyboardview: abcKeyboard!,
                                                       inputView: textFiled!,
                                                       onKeyClickListener: onClickListener!)
       textFiled?.reloadInputViews()
    }
    

}

  • 隨機(jī)數(shù)字鍵盤(pán)類(lèi)
import UIKit

class RandomNumberKeyboard: KeyboardBaseView {

    lazy var logoLabel        : UILabel = UILabel()
    var colSpace              : CGFloat = 5.0;
    var rowSpace              : CGFloat = 5.0
    lazy var randomNumArray   : NSMutableArray = NSMutableArray.init()
    
    override init(frame: CGRect) {
       super.init(frame: frame)
       self.backgroundColor = UIColor.gray
       createLogoView()
        
        for i in 0..<10 {
            randomNumArray.add(NSString.init(format: "%d", i))
        }
    }
       
   required init?(coder: NSCoder) {
       fatalError("init(coder:) has not been implemented")
   }
    
    func createLogoView(){
        self.logoLabel.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: 44)
        self.addSubview(self.logoLabel)
        self.logoLabel.text = "硬漢安全鍵盤(pán)"
        self.logoLabel.textAlignment = .center
        logoLabel.font = UIFont.systemFont(ofSize: 14)
        logoLabel.textColor = UIColor.white
        
        let btnFinish = UIButton.init()
        btnFinish.frame = CGRect.init(x: self.frame.size.width - 100, y: 0, width: 100, height: 44)
        self.addSubview(btnFinish)
        btnFinish.tag = FINISH
        btnFinish.setTitle("完成", for: .normal)
        btnFinish.setTitleColor(UIColor.blue, for: .normal)
        btnFinish.addTarget(self, action: #selector(onClickListener(button:)), for:.touchUpInside)
        
    }
    
    override func createView(inputView targetView: UITextField, addOnClickListener listener: OnKeyListener) {
        super.createView(inputView: targetView, addOnClickListener: listener)
        createNumberAndRandom()
    }
    
    func createNumberAndRandom() {
        //隨機(jī)亂序
        for i in (1...10).reversed() {
            let random = arc4random_uniform(UInt32(i))
            let tmp = self.randomNumArray[Int(random)];
            self.randomNumArray[Int(random)] = self.randomNumArray[i - 1];
            self.randomNumArray[i - 1] = tmp;
        }
        
        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, item)in randomNumArray.enumerated(){
            
            if(i == 0){
                createKey(titleTxt: item as! String,
                          posX: self.colSpace * 2 +  width,
                          posY: self.logoLabel.frame.size.height + self.rowSpace * 3 + height * 3,
                          width: width,
                          hight: height,
                          forId: i,
                          normalImg: "anniu1.png",
                          highLightimg: "anniu1_select.png")
                
            }else{
            
               let indexColSpace = self.colSpace + self.colSpace * CGFloat(i % 3)
               let indexWidth = width * CGFloat(i % 3)
               let x = indexColSpace +  indexWidth
               
               let indexRowSpace = self.logoLabel.frame.size.height + self.rowSpace * CGFloat((i - 1) / 3)
               let indexRowHeight = height * CGFloat((i - 1) / 3)
               let y = indexRowSpace + indexRowHeight
               
                createKey(titleTxt: item as! String,
                            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 + height * 3,
                             width: width,
                             hight: height,
                             forId: ABC,
                             normalImg: "anniu1.png",
                             highLightimg: "anniu1_select.png")

        
        createKey(titleTxt: "X",
                        posX: self.colSpace * 3 + width * 2,
                        posY: self.logoLabel.frame.size.height + self.rowSpace * 3 + height * 3,
                        width: width,
                        hight: height,
                        forId: DELETE,
                        normalImg: "anniu1.png",
                        highLightimg: "anniu1_select.png")
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        createNumberAndRandom()
    }

}

  • 英文鍵盤(pán)類(lèi)
import UIKit

let SCREEN_WIDTH = UIScreen.main.bounds.width
let SCREEN_HEIGHT = UIScreen.main.bounds.height
let FIT_WIDTH = SCREEN_WIDTH / 320.0


class AbcKeyboard: KeyboardBaseView {

    lazy var array = NSMutableArray.init(objects:
        "q","w","e","r","t","y","u","i","o","p",
        "a","s","d","f","g","h","j","k","l",
        "z","x","c","v","b","n","m")
    var capitalKeyBgImg :UIImageView?
    
    override func createView(inputView targetView: UITextField, addOnClickListener listener: OnKeyListener) {
        super.createView(inputView: targetView, addOnClickListener: listener)
        for view in self.subviews{
            view.removeFromSuperview()
        }

        self.backgroundColor = UIColor.init(patternImage: UIImage.init(named: "bgs.png")!)
        for i in 0..<10{
            createKey(titleTxt: array[i] as! String,
                          posX: 1 + CGFloat(i) * 32.0 * FIT_WIDTH,
                          posY: 5 * FIT_WIDTH,
                         width: 34 * FIT_WIDTH,
                         hight: 48 * FIT_WIDTH,
                         forId: i + 100,
                     normalImg: "tu1 (2).png",
                  highLightimg: "tu1 2.png")
        }
        
        for i in 0..<9{
            createKey(titleTxt: array[i + 10] as! String,
                          posX: 16 + CGFloat(i) * 32.0 * FIT_WIDTH,
                          posY: 53 * FIT_WIDTH,
                         width: 34 * FIT_WIDTH,
                         hight: 48 * FIT_WIDTH,
                         forId: i + 110,
                     normalImg: "tu1 (2).png",
                  highLightimg: "tu1 2.png")
        }
        
        for i in 0..<7{
            createKey(titleTxt: array[i + 19] as! String,
                      posX: 46.0 * FIT_WIDTH + CGFloat(i) * 32.0 * FIT_WIDTH,
                          posY: 103 * FIT_WIDTH,
                         width: 34 * FIT_WIDTH,
                         hight: 48 * FIT_WIDTH,
                         forId: i + 119,
                     normalImg: "tu1 (2).png",
                  highLightimg: "tu1 2.png")
        }
        
        //刪除鍵
        createKey(titleTxt: "",
                  posX: 272.0 * FIT_WIDTH,
                posY: 103 * FIT_WIDTH,
               width: 43 * FIT_WIDTH,
               hight: 49 * FIT_WIDTH,
               forId: DELETE,
           normalImg: "tu2 2.png",
        highLightimg: "tu2 (2).png")
        
        let deleteKeyBgImg = UIImageView.init(frame: CGRect.init(x: 277*FIT_WIDTH, y:113*FIT_WIDTH, width:32*FIT_WIDTH, height:28*FIT_WIDTH))
        deleteKeyBgImg.image = UIImage.init(named: "tu2 (3).png")
        self.addSubview(deleteKeyBgImg)
        
        //大小切換鍵
        createKey(titleTxt: "",
                  posX: 1.0 ,
                posY: 103 * FIT_WIDTH,
               width: 43 * FIT_WIDTH,
               hight: 49 * FIT_WIDTH,
               forId: CAPTIAL,
           normalImg: "tu2 2.png",
        highLightimg: "tu2 (2).png")
        
        let capitalKey = self.viewWithTag(CAPTIAL) as! UIButton
        capitalKey.setBackgroundImage(UIImage.init(named: "tu2 (2).png"), for: .selected)
        
        capitalKeyBgImg = UIImageView.init(frame: CGRect.init(x: 7*FIT_WIDTH, y:113*FIT_WIDTH, width:31*FIT_WIDTH, height:27*FIT_WIDTH))
        capitalKeyBgImg!.image = UIImage.init(named: "da_.png")
        self.addSubview(capitalKeyBgImg!)
        
        //數(shù)字123鍵
        createKey(titleTxt: "",
                  posX: 1.0 ,
                posY: 152 * FIT_WIDTH,
               width: 80 * FIT_WIDTH,
               hight: 49 * FIT_WIDTH,
               forId: SWITCH_TYPE,
           normalImg: "tu3-4",
        highLightimg: "tu3-04 (2).png")
        
        let num123Label = UILabel.init()
        num123Label.frame = self.viewWithTag(SWITCH_TYPE)!.frame
        num123Label.backgroundColor = UIColor.clear
        num123Label.textColor = UIColor.white
        num123Label.textAlignment = .center
        num123Label.font = UIFont.init(name: "STHeitiSC-Light", size: 18.0 * FIT_WIDTH)
        num123Label.text = "1 2 3"
        self.addSubview(num123Label)
        
        //space鍵
        createKey(titleTxt: " ",
                  posX: 80 * FIT_WIDTH,
                posY: 152 * FIT_WIDTH,
               width: 160 * FIT_WIDTH,
               hight: 49 * FIT_WIDTH,
               forId: SPACE,
           normalImg: "tu4 (2).png",
        highLightimg: "tu4 2.png")
        
        let spaceLabel = UILabel.init()
        spaceLabel.frame = self.viewWithTag(SPACE)!.frame
        spaceLabel.backgroundColor = UIColor.clear
        spaceLabel.textColor = UIColor.white
        spaceLabel.textAlignment = .center
        spaceLabel.font = UIFont.init(name: "STHeitiSC-Light", size: 18.0 * FIT_WIDTH)
        spaceLabel.text = " "
        self.addSubview(spaceLabel)
        
        createKey(titleTxt: " ",
                  posX: SCREEN_WIDTH - 80 * FIT_WIDTH,
                posY: 152 * FIT_WIDTH,
               width: 80 * FIT_WIDTH,
               hight: 49 * FIT_WIDTH,
               forId: SEARCH,
           normalImg: "tu4 (2).png",
        highLightimg: "tu4 2.png")
        
        let searchLabel = UILabel.init()
        searchLabel.frame = self.viewWithTag(SEARCH)!.frame
        searchLabel.backgroundColor = UIColor.clear
        searchLabel.textColor = UIColor.blue
        searchLabel.textAlignment = .center
        searchLabel.font = UIFont.init(name: "STHeitiSC-Light", size: 14.0 * FIT_WIDTH)
        searchLabel.text = "搜索"
        self.addSubview(searchLabel)
    }
    
    override func switchCaptial(button view: UIButton) {
        if view.isSelected {
            view.isSelected = false
            capitalKeyBgImg?.image = UIImage.init(named: "da_.png")
            
            for(idx,obj) in array.enumerated(){
                let tmp = obj as! String
                array[idx] = tmp.lowercased()
                let key = self.viewWithTag(100 + idx) as! UIButton
                key.setTitle(tmp.lowercased(), for: .normal)
            }
            
        }else{
            view.isSelected = true
            capitalKeyBgImg?.image = UIImage.init(named: "da.png")
            for(idx,obj) in array.enumerated(){
                let tmp = obj as! String
                array[idx] = tmp.uppercased()
                let key = self.viewWithTag(100 + idx) as! UIButton
                key.setTitle(tmp.uppercased(), for: .normal)
            }
            
        }
         
    }
    
    override func switchKeyboardType() {
        var numKeyboard = KeyboardMgr.shareInstace.keyboardInstanceDict[NumberKeyboard.self.description()]
        if(numKeyboard == nil){
            numKeyboard = NumberKeyboard.init(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 260))
            KeyboardMgr.shareInstace.keyboardInstanceDict[NumberKeyboard.self.description()] = numKeyboard
        }
        KeyboardMgr.shareInstace.setInputMethodKeyboard(keyboardview: numKeyboard!,
                                                        inputView: textFiled!,
                                                        onKeyClickListener: onClickListener!)
        textFiled?.reloadInputViews()
    }

}

  • 測(cè)試使用例子
import UIKit

class KeyboardVC: UIViewController {
    
    lazy var textFiled : UITextField = UITextField.init(frame: CGRect.init(x: 20, y: 150, width: 100, height: 50))

    override func viewDidLoad() {
        super.viewDidLoad()

        //重新創(chuàng)建一個(gè)barButtonItem
        self.navigationController?.isNavigationBarHidden = false

        let backItem = UIBarButtonItem.init(title: "Back", style: .done, target: self, action: #selector(onClickListener))
        backItem.tag = 50
        //設(shè)置backBarButtonItem即可
        self.navigationItem.leftBarButtonItem = backItem;
        self.navigationItem.title = "標(biāo)題文字"
        self.view.backgroundColor = UIColor.white
        
    
        textFiled.backgroundColor = UIColor.gray
        self.view.addSubview(textFiled)
        
        let keyBoardView = AbcKeyboard.init(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 260))
        
        KeyboardMgr.init().setInputMethodKeyboard(keyboardview: keyBoardView, inputView: textFiled, onKeyClickListener: self)
        
        
    
        
        
    }
    
    @objc func onClickListener(){
        self.navigationController?.popViewController(animated: false)
    }
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

//實(shí)現(xiàn)鍵盤(pán)按鈕點(diǎn)擊協(xié)議
extension KeyboardVC:OnKeyListener{
    
    func onClick(button view: UIButton) {
        print("60---\(String(describing: view.titleLabel?.text))")
    }
    
    func addTextWatch(button view: UIButton, beforeText bStr: String?, curText cStr: String?, afterText aStr: String?) {
        print("65-----beforetext:\(bStr) curtext:\(cStr) aftertext:\(aStr)")
        textFiled.text = aStr
    }
}

objc 版本:

#import <UIKit/UIKit.h>

typedef NS_ENUM(NSInteger, KeyboardType) {
    DecimalNumber       = 0, //帶小數(shù)點(diǎn)的數(shù)據(jù)鍵盤(pán) 九宮格布局
    NumberAndRandom     = 1, //隨機(jī)出現(xiàn)數(shù)字鍵盤(pán)  九宮格布局
    Number              = 3, //純數(shù)字鍵盤(pán)
    Default             = 4, //默認(rèn)的英文鍵盤(pán) 26鍵布局
  
};


/// 鍵盤(pán)點(diǎn)擊協(xié)議
@protocol OnKeyListener <NSObject>


@optional

/// 按鍵點(diǎn)擊事件
/// @param Id 按鍵id
/// @param text 當(dāng)前的文本
/// @param btn 按鍵對(duì)象
- (void)onClick:(NSInteger)Id withText:(NSString *_Nullable)text view:(UIButton*_Nullable) btn;

@optional
/// 文本輸入監(jiān)聽(tīng)協(xié)議接口
/// @param view 按鍵本身
/// @param beforeText 上一次輸入的文本
/// @param curText 當(dāng)前輸入的文本
/// @param afterText 輸入之后的文本
-(void) onTextWatch:(UIButton*_Nullable) view
         beforeText:(NSString*_Nullable) beforeText
            curText:(NSString*_Nullable)curText
          afterText:(NSString*_Nullable)afterText;

@end



NS_ASSUME_NONNULL_BEGIN

@interface KeyboardView : UIView
@property(assign,nonatomic) NSUInteger colSpace;
@property(assign,nonatomic) NSUInteger rowSpace;
@property(strong,nonatomic) UIView* containerView;
@property(strong, nonatomic) UITextField *tmpTextField;
@property(weak,nonatomic) id<OnKeyListener> keyClickListener;
@property(nonatomic,assign) KeyboardType type;


///  設(shè)置輸入法鍵盤(pán)
/// @param type 類(lèi)型
/// @param inputView 輸入視圖
-(void) setInputMethodKeyboard:(KeyboardType) type inputView:(UITextField*) inputView;

-(void) releaseRes;

@end

NS_ASSUME_NONNULL_END


#import "KeyboardView.h"
#import "AbcKeyBoardView.h"
#import <Foundation/Foundation.h>
#import "NSString+Des3.h"

#define FIT_X          [UIScreen mainScreen].bounds.size.width/320.000
#define iPhone4        ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(640, 960), [[UIScreen mainScreen] currentMode].size) : NO)

const NSInteger ABC     = 23;
const NSInteger DELETE  = 24;

@interface KeyboardView(){
    UIButton *pressButtonCapital;
}
@property(strong,nonatomic) UIView* logoBgView;
@property(copy,nonatomic) NSString* beforeInputContent; //注意此處的修飾符碴开,before為臨時(shí)m賦值邻吞,用copy
@property(strong,nonatomic) NSMutableArray* randomNumArray;
@property(strong,nonatomic) AbcKeyBoardView* abcKeyboardView;

// 不能使用copy 因?yàn)榭勺儗?duì)象的拷貝之后變成了為不可變對(duì)象针余,不能再進(jìn)行內(nèi)容追加
@property(strong,nonatomic) NSMutableString* afterInputContent;

@end

@implementation KeyboardView


- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self initConfig];
    }
    return self;
}

-(void) initConfig{
    self.rowSpace = 5;
    self.colSpace = 5;
    self.containerView = [UIView new];
    self.containerView.frame = self.frame;
    [self addSubview:self.containerView];
    self.afterInputContent = [[NSMutableString alloc] init];
    self.randomNumArray = [[NSMutableArray alloc] init];
    for (NSInteger i = 0;  i < 10; i ++) {
        [self.randomNumArray addObject:[NSString stringWithFormat:@"%ld",i]];
    }
}

/// 設(shè)置輸入法鍵盤(pán)
/// @param type 類(lèi)型
/// @param inputView 輸入視圖
-(void) setInputMethodKeyboard:(KeyboardType) type inputView:(UITextField*) inputView{
    if (!inputView) {
        return;
    }
    self.type = type;
    inputView.inputView = self;
    self.tmpTextField = inputView;
    switch (type) {
        case Default:
            [self createDefaultKeyvoardView];
            break;
        case Number:{
            [self createLogoView];
            [self createNumberKeyboardView];
            
        }
            break;
            
        case NumberAndRandom:
            [self createLogoView];
            break;
            
        default:
            break;
    }
}

- (void)createLogoView{
    self.logoBgView = [UIView new];
    [self setBackgroundColor:[UIColor darkGrayColor]];
    [self.containerView addSubview:self.logoBgView];
    self.logoBgView.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 44);

    UILabel *logoLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.logoBgView.frame), CGRectGetHeight(self.logoBgView.frame))];
    [self.logoBgView addSubview:logoLabel];
    [logoLabel setText:@"硬漢安全鍵盤(pán)"];
    logoLabel.textAlignment = NSTextAlignmentCenter;
    [logoLabel setLineBreakMode:NSLineBreakByWordWrapping];
    [logoLabel setNumberOfLines:0];
    [logoLabel setFont:[UIFont systemFontOfSize:14]];
    [logoLabel setTextColor:[UIColor whiteColor]];

    UIButton *btnFinish = [[UIButton alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.logoBgView.frame) / 4 * 3, 0, CGRectGetWidth(self.logoBgView.frame) / 4 , CGRectGetHeight(self.logoBgView.frame))];
    [self.logoBgView addSubview:btnFinish];
    [btnFinish setTitle:@"完成" forState:UIControlStateNormal];
    [btnFinish setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [btnFinish addTarget:self action:@selector(hideKeyboard) forControlEvents:UIControlEventTouchUpInside];
}

-(void) createNumberKeyboardView{
    CGFloat width = (CGRectGetWidth(self.frame) - self.colSpace * 4) / 3;
    CGFloat height = (CGRectGetHeight(self.frame) - self.rowSpace * 4 - self.logoBgView.frame.size.height) / 4 ;
    for(NSInteger i = 1; i < 10; i ++){
        [self createKey:[NSString stringWithFormat:@"%ld",i]
                   posX:(self.colSpace + self.colSpace * ((i - 1) % 3) +  width * ((i - 1) % 3))
                   posY:(44 + self.rowSpace * ((i - 1) / 3) + height * ((i - 1)/3))
                  width:width
                 height:height
                  forId:i];
    }
    //創(chuàng)建最底部一排的功能鍵
    [self createKey:[NSString stringWithFormat:@"%@",@"ABC"]
               posX:(self.colSpace)
               posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
              width:width
             height:height
              forId:23];

    [self createKey:[NSString stringWithFormat:@"%@",@"0"]
                  posX:(self.colSpace * 2 +  width)
                  posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
                 width:width
                height:height
                 forId:0];

    [self createKey:[NSString stringWithFormat:@"%@",@"X"]
               posX:(self.colSpace * 3 +  width * 2)
               posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
              width:width
             height:height
              forId:24];
    
}


/// 創(chuàng)建隨機(jī)數(shù)字鍵盤(pán)芯急,即0-9數(shù)字在鍵盤(pán)的位置隨機(jī)出現(xiàn)
-(void) createNumberAndRandom{
    //隨機(jī)打亂
    for(NSInteger i = self.randomNumArray.count;i > 0; i --){
        NSInteger random = arc4random() % i;
        NSInteger tmp = [self.randomNumArray[random] intValue];
        self.randomNumArray[random] = self.randomNumArray[i - 1];
        self.randomNumArray[i - 1] = [NSNumber numberWithInteger:tmp];
    }
    CGFloat width = (CGRectGetWidth(self.frame) - self.colSpace * 4) / 3;
    CGFloat height = (CGRectGetHeight(self.frame) - self.rowSpace * 4 - self.logoBgView.frame.size.height) / 4 ;
    
    [self.randomNumArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
        NSString* value = [NSString stringWithFormat:@"%@",obj];
        if(idx == 0){
            [self createKey:value
                      posX:(self.colSpace * 2 +  width)
                      posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
                     width:width
                    height:height
                     forId:[value intValue]];
        }else{
            [self createKey:value
                      posX:(self.colSpace + self.colSpace * ((idx) % 3) +  width * ((idx) % 3))
                      posY:(self.logoBgView.frame.size.height + self.rowSpace * ((idx - 1) / 3) + height * ((idx - 1)/3))
                     width:width
                    height:height
                     forId:[value intValue]];
        }
    }];
    [self createKey:[NSString stringWithFormat:@"%@",@"ABC"]
              posX:(self.colSpace)
              posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
             width:width
            height:height
             forId:ABC];
    
    [self createKey:[NSString stringWithFormat:@"%@",@"X"]
              posX:(self.colSpace * 3 +  width * 2)
              posY:(self.logoBgView.frame.size.height + self.rowSpace * 3 + height * 3)
             width:width
            height:height
             forId:DELETE];
    
}


/// 創(chuàng)建英文字母鍵盤(pán)豌蟋,默認(rèn)的類(lèi)型為本鍵盤(pán)
-(void) createDefaultKeyvoardView{
    self.abcKeyboardView = [[AbcKeyBoardView alloc] initWithFrame:self.frame];
    [self.abcKeyboardView createKeyboardView];
    [self addSubview:self.abcKeyboardView];
    
}

-(void) removeAllSubViews:(UIView*) parentView{
    if (parentView) {
        for(UIView *view in [parentView subviews]){
            [view removeFromSuperview];
        }
    }
}

- (void)createKey:(NSString *)title
             posX:(float)posX
             posY:(float)posY
            width:(float)width
           height:(float)height
            forId:(NSInteger) tag{
    UIButton *btnKey = [[UIButton alloc]initWithFrame:CGRectMake(posX, posY, width, height)];
    [self.containerView addSubview:btnKey];
    btnKey.layer.cornerRadius = 5;
    btnKey.tag = tag;
    [btnKey addTarget:self action:@selector(buttonDidClicked:) forControlEvents:UIControlEventTouchUpInside];
    [btnKey setTitle:title forState:UIControlStateNormal];
    [btnKey setBackgroundColor:[UIColor lightGrayColor]];
    //[btnKey setBackgroundImage:[CommonFunc imageWithColor:[UIColor orangeColor]] forState:UIControlStateHighlighted];
}

- (void)buttonDidClicked:(UIButton*)sender{
    self.tmpTextField.text = sender.titleLabel.text;
    
    switch (sender.tag) {
            
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 0:
            [self.afterInputContent appendString:sender.titleLabel.text];
        break;
            
        case ABC:
            
            break;
            
        case DELETE:{
            if(self.afterInputContent.length > 0){
                NSString* minusStr = [self.afterInputContent substringToIndex:self.afterInputContent.length - 1];
                [self.afterInputContent setString:minusStr] ;
            }
        }
            
            break;
            
        default:
            break;
    }
   
    if ([self.keyClickListener respondsToSelector:@selector(onClick:withText:view:)]) {
           [self.keyClickListener onClick:sender.tag withText:sender.titleLabel.text view:sender];
       }
    if ([self.keyClickListener respondsToSelector:@selector(onTextWatch:beforeText:curText:afterText:)]) {
        
        [self.keyClickListener onTextWatch:sender beforeText:self.beforeInputContent curText:sender.titleLabel.text afterText:self.afterInputContent];
        self.beforeInputContent = self.afterInputContent;
    }
       
}


- (void)willMoveToSuperview:(UIView *)newSuperview{
    if (self.type == NumberAndRandom) {
        [self createNumberAndRandom];
    }
    
}

-(void)layoutSubviews{
    [super layoutSubviews];

}

- (void)hideKeyboard{
    [self.tmpTextField endEditing:YES];
    //[self.tmpTextField resignFirstResponder];
}

-(void) releaseRes{
    self.beforeInputContent = nil;
    self.afterInputContent = nil;
}

@end


  • 測(cè)試
@interface KeyboardVC ()<OnKeyListener>
@property(strong,nonatomic) UITextField* textField;
@property(strong,nonatomic) KeyboardView* keyboardView;

@end

@implementation KeyboardVC

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(20, 40, 200, 50)];
    self.textField.backgroundColor = [UIColor grayColor];
    [self.view addSubview:self.textField];
    
    self.keyboardView = [[KeyboardView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, 260)];
    
    //self.textField.inputView = self.keyboardView;
    //self.keyboardView.m_textField = self.textField;
    [self.keyboardView setInputMethodKeyboard:Number inputView:self.textField];
    [self.keyboardView setKeyClickListener:self];
    
    [self setUpForDismissKeyboard];

    
}
#pragma OnKeyListener 協(xié)議實(shí)現(xiàn)方式
- (void)onClick:(NSInteger)Id withText:(NSString *)text view:(UIButton *)btn{
    
}
-(void) onTextWatch:(UIButton*_Nullable) view
         beforeText:(NSString*_Nullable) beforeText
            curText:(NSString*_Nullable) curText
          afterText:(NSString*_Nullable) afterText{
    NSLog(@"37-------before:%@  curtext:%@  afterText:%@",beforeText,curText,afterText);
    self.textField.text = afterText;
   
}
//  end

//除輸入框之外 速和,點(diǎn)擊屏幕其他地方收起鍵盤(pán)
- (void)setUpForDismissKeyboard {
  NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
  UITapGestureRecognizer *singleTapGR =
  [[UITapGestureRecognizer alloc] initWithTarget:self
                                          action:@selector(tapAnywhereToDismissKeyboard:)];
  NSOperationQueue *mainQuene =[NSOperationQueue mainQueue];
  [nc addObserverForName:UIKeyboardWillShowNotification
                  object:nil
                   queue:mainQuene
              usingBlock:^(NSNotification *note){
                [self.view addGestureRecognizer:singleTapGR];
              }];
  [nc addObserverForName:UIKeyboardWillHideNotification
                  object:nil
                   queue:mainQuene
              usingBlock:^(NSNotification *note){
                [self.view removeGestureRecognizer:singleTapGR];
              }];
}

- (void)tapAnywhereToDismissKeyboard:(UIGestureRecognizer *)gestureRecognizer {
  [self.view endEditing:YES];
}


@end

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末歹垫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子颠放,更是在濱河造成了極大的恐慌排惨,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碰凶,死亡現(xiàn)場(chǎng)離奇詭異暮芭,居然都是意外死亡鹿驼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)辕宏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畜晰,“玉大人,你說(shuō)我怎么就攤上這事瑞筐∠象埃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵面哼,是天一觀(guān)的道長(zhǎng)野宜。 經(jīng)常有香客問(wèn)我,道長(zhǎng)魔策,這世上最難降的妖魔是什么匈子? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮闯袒,結(jié)果婚禮上虎敦,老公的妹妹穿的比我還像新娘。我一直安慰自己政敢,他們只是感情好其徙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著喷户,像睡著了一般唾那。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上褪尝,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天闹获,我揣著相機(jī)與錄音,去河邊找鬼河哑。 笑死避诽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的璃谨。 我是一名探鬼主播沙庐,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼佳吞!你這毒婦竟也來(lái)了拱雏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤容达,失蹤者是張志新(化名)和其女友劉穎古涧,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體花盐,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡羡滑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了算芯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柒昏。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖熙揍,靈堂內(nèi)的尸體忽然破棺而出职祷,到底是詐尸還是另有隱情,我是刑警寧澤届囚,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布有梆,位于F島的核電站,受9級(jí)特大地震影響意系,放射性物質(zhì)發(fā)生泄漏泥耀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一蛔添、第九天 我趴在偏房一處隱蔽的房頂上張望痰催。 院中可真熱鬧,春花似錦迎瞧、人聲如沸夸溶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)缝裁。三九已至,卻和暖如春足绅,著一層夾襖步出監(jiān)牢的瞬間压语,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工编检, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胎食,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓允懂,卻偏偏與公主長(zhǎng)得像厕怜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蕾总,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354