天天看點

IOS自定義鍵盤(swift/Objc)

效果圖

IOS自定義鍵盤(swift/Objc)

自定義鍵盤的核心思想

  • 設定UITextFiled 的InputView
  • 切換鍵盤的思路為重新設定UITextFiled 的InputView然後再調用textFiled?.reloadInputViews()

    *剩下的就是按鍵的布局與代理設定了

swift版本采用政策模式實作,Objc版本使用正常模式實作

  • 政策模式請參看另一編文章https://blog.csdn.net/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 + 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 = "硬漢安全鍵盤"
        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()
    }
    

}

           
  • 随機數字鍵盤類
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 = "硬漢安全鍵盤"
        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() {
        //随機亂序
        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()
    }

}

           
  • 英文鍵盤類
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!)
        
        //數字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()
    }

}

           
  • 測試使用例子
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()

        //重新建立一個barButtonItem
        self.navigationController?.isNavigationBarHidden = false

        let backItem = UIBarButtonItem.init(title: "Back", style: .done, target: self, action: #selector(onClickListener))
        backItem.tag = 50
        //設定backBarButtonItem即可
        self.navigationItem.leftBarButtonItem = backItem;
        self.navigationItem.title = "标題文字"
        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.
    }
    */

}

//實作鍵盤按鈕點選協定
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, //帶小數點的資料鍵盤 九宮格布局
    NumberAndRandom     = 1, //随機出現數字鍵盤  九宮格布局
    Number              = 3, //純數字鍵盤
    Default             = 4, //預設的英文鍵盤 26鍵布局
  
};


/// 鍵盤點選協定
@protocol OnKeyListener <NSObject>


@optional

/// 按鍵點選事件
/// @param Id 按鍵id
/// @param text 目前的文本
/// @param btn 按鍵對象
- (void)onClick:(NSInteger)Id withText:(NSString *_Nullable)text view:(UIButton*_Nullable) btn;

@optional
/// 文本輸入監聽協定接口
/// @param view 按鍵本身
/// @param beforeText 上一次輸入的文本
/// @param curText 目前輸入的文本
/// @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;


///  設定輸入法鍵盤
/// @param type 類型
/// @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為臨時m指派,用copy
@property(strong,nonatomic) NSMutableArray* randomNumArray;
@property(strong,nonatomic) AbcKeyBoardView* abcKeyboardView;

// 不能使用copy 因為可變對象的拷貝之後變成了為不可變對象,不能再進行内容追加
@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]];
    }
}

/// 設定輸入法鍵盤
/// @param type 類型
/// @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:@"硬漢安全鍵盤"];
    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];
    }
    //建立最底部一排的功能鍵
    [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];
    
}


/// 建立随機數字鍵盤,即0-9數字在鍵盤的位置随機出現
-(void) createNumberAndRandom{
    //随機打亂
    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];
    
}


/// 建立英文字母鍵盤,預設的類型為本鍵盤
-(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


           
  • 測試
@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 協定實作方式
- (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

//除輸入框之外 ,點選螢幕其他地方收起鍵盤
- (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