IOS自定义键盘

效果图

QQ20200527-152722-HD.gif

自定义键盘的核心思想

  • 设置UITextFiled 的InputView
  • 切换键盘的思路为重新设置UITextFiled 的InputView然后再调用textFiled?.reloadInputViews()
    *剩下的就是按键的布局与代理设置了

swift版本采用策略模式实现,Objc版本使用常规模式实现

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350