年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 4358|回复: 4

iOS制作自定义数字键盘

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2015-5-20 13:33:28 | 显示全部楼层 |阅读模式
    一、应用场景

           很多情况下我们的输入都是有硬性要求的,比如只能输入数字,通常情况下我们的解决方案就是指定输入框的键盘模式(keyboardType),可系统提供给我的键盘种类还是非常有限的,如下所示:
    [Objective-C] 纯文本查看 复制代码
    typedef NS_ENUM(NSInteger, UIKeyboardType) {
        UIKeyboardTypeDefault,                // Default type for the current input method.
        UIKeyboardTypeASCIICapable,           // Displays a keyboard which can enter ASCII characters, non-ASCII keyboards remain active
        UIKeyboardTypeNumbersAndPunctuation,  // Numbers and assorted punctuation.
        UIKeyboardTypeURL,                    // A type optimized for URL entry (shows . / .com prominently).
        UIKeyboardTypeNumberPad,              // A number pad (0-9). Suitable for PIN entry.
        UIKeyboardTypePhonePad,               // A phone pad (1-9, *, 0, #, with letters under the numbers).
        UIKeyboardTypeNamePhonePad,           // A type optimized for entering a person's name or phone number.
        UIKeyboardTypeEmailAddress,           // A type optimized for multiple email address entry (shows space @ . prominently).
        UIKeyboardTypeDecimalPad NS_ENUM_AVAILABLE_IOS(4_1),   // A number pad with a decimal point.
        UIKeyboardTypeTwitter NS_ENUM_AVAILABLE_IOS(5_0),      // A type optimized for twitter text entry (easy access to @ #)
        UIKeyboardTypeWebSearch NS_ENUM_AVAILABLE_IOS(7_0),    // A default keyboard type with URL-oriented addition (shows space . prominently).
    
        UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable, // Deprecated
    
    };
    有时候可能不能满足我们的需要,比如在数字键盘中需要增加一个完成按钮等等,我们在现有的键盘上动手脚都无法完美解决我们所遇到的问题,最好的办法就是自定义一个符合我们需求的键盘。

    二、示例效果

    iOS Simulator Screen Shot 2015年5月20日 下午1.39.56.png
    如何能实现这种效果呢,其实使用非常简单,就一行代码:
    [Objective-C] 纯文本查看 复制代码
    self.textField.keyboardType = SAKeyboardTypeNumber;

    三、设计原理

           类似于UITextField这样的文本输入控件,一般都有一个inputView属性,这个属性就是用来指定自定义键盘的,还有一个inputAccessoryView属性,用来在键盘上方增加自定义的工具条或控件,我们自定义键盘就从inputView这个属性上做文章。
           然而在使用的时候,我又希望能保持系统风格,即通过setKeyboardType:这个方法,或者改变keyboardType这个枚举值来达到指定自定义键盘的目的,看起来一切都是那么的自然,就好像扩展了系统键盘类型这种效果,我个人认为这种封装是最好的,不用改变开发者的使用习惯!
           由于要改变setKeyboardType:这个方法,无法通过Category实现,只能自定义一个TextField继承自UITextField来覆盖这个方法,如果不想这样做,那就只能通过inputView属性来实现,我这里只介绍前者,我认为重写没什么不好,并且项目上很多系统的类都是需要重写的,重写可以统一风格,统一调整,重写还可以积累自己的一些好用的东西,最终可以积累出一个属于自己的库!
           另外一点,这个键盘需要事先通过xib画好,每一个键可以使用按钮来实现,排版布局这里不做太多说明,实现输入则是调用TextField的replaceRange:withText这个就去来实现        

    四、代码说明

    1、SATextField.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SATextField.h
    //  Test
    //
    //  Created by 余西安 on 15/5/16.
    //  Copyright (c) 2015年 Sian. All rights reserved.
    //
    typedef enum {
        SAKeyboardTypeNumber
    }SAKeyboardType;
    
    #import <UIKit/UIKit.h>
    
    @interface SATextField : UITextField
    
    - (void)setKeyboardType:(SAKeyboardType)keyboardType;
    
    @end

    2、SATextField.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  SATextField.m
    //  Test
    //
    //  Created by 余西安 on 15/5/16.
    //  Copyright (c) 2015年 Sian. All rights reserved.
    //
    
    #import "SATextField.h"
    #import "SANumberKeyboard.h"
    
    @implementation SATextField
    
    - (void)setKeyboardType:(SAKeyboardType)keyboardType
    {
        switch (keyboardType) {
            case SAKeyboardTypeNumber:{
                SANumberKeyboard *keyboard = [SANumberKeyboard keyboardWithTextField:self];
                self.inputView = keyboard;
                
            }break;
                
            default: [super setKeyboardType:(UIKeyboardType)keyboardType]; break;
        }
    }
    
    @end

    3、SANumberKeyboard.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SANumberKeyboard.h
    //  Test
    //
    //  Created by 余西安 on 15/5/16.
    //  Copyright (c) 2015年 Sian. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    #import "SATextField.h"
    
    @interface SANumberKeyboard : UIView
    
    @property (nonatomic, weak) SATextField *textField;
    
    + (instancetype)keyboardWithTextField:(SATextField *)textField;
    
    @end

    4、SANumberKeyboard.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  SANumberKeyboard.m
    //  Test
    //
    //  Created by 余西安 on 15/5/16.
    //  Copyright (c) 2015年 Sian. All rights reserved.
    //
    
    #import "SANumberKeyboard.h"
    
    @implementation SANumberKeyboard
    
    + (instancetype)keyboardWithTextField:(SATextField *)textField;
    {
        SANumberKeyboard *keyboard = [[self alloc] init];
        keyboard.textField = textField;
        return keyboard;
    }
    
    - (instancetype)init
    {
        self = [[[NSBundle mainBundle] loadNibNamed:@"SANumberKeyboard" owner:nil options:nil] firstObject];
        for (UIButton *btn in self.subviews) {
            if (btn.tag == 0) continue;
            UIImage *image = [self imageWithColor:[UIColor whiteColor]];
            UIImage *image1 = [self imageWithColor:[UIColor colorWithWhite:0.8 alpha:1.0]];
            if (btn.tag <= 10)[btn setBackgroundImage:image forState:UIControlStateNormal];
            if (btn.tag > 10)[btn setBackgroundImage:image1 forState:UIControlStateNormal];
            [btn addTarget:self action:@selector(buttonEven:) forControlEvents:UIControlEventTouchUpInside];
        }
        return self;
    }
    
    /// 指定颜色生成一张大小为(1,1)的图片
    - (UIImage *)imageWithColor:(UIColor *)color
    {
        CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        return image;
    }
    
    /// 各按键事件
    - (void)buttonEven:(UIButton *)button
    {
        UITextRange *textRange = self.textField.selectedTextRange;
        NSString *string = @"";
        switch (button.tag) {
            case  1: string = @"1"; break;
            case  2: string = @"2"; break;
            case  3: string = @"3"; break;
            case  4: string = @"4"; break;
            case  5: string = @"5"; break;
            case  6: string = @"6"; break;
            case  7: string = @"7"; break;
            case  8: string = @"8"; break;
            case  9: string = @"9"; break;
            case 10: string = @"0"; break;
            case 11: string = @"."; break;
            case 12:{
                if (textRange.isEmpty){
                    UITextPosition *from = [self.textField positionFromPosition:textRange.start offset:-1];
                    UITextPosition *to = [self.textField positionFromPosition:textRange.start offset:0];
                    textRange = [self.textField textRangeFromPosition:from toPosition:to];
                }
            }break;
            default:break;
        }
        [self.textField replaceRange:textRange withText:string];
    }
    
    @end

    五、源码下载(Demo)
    游客,如果您要查看本帖隐藏内容请回复

    该控件纯属抛砖引玉,通过这种思路能做的事情还非常的多!!

    该用户从未签到

    发表于 2015-5-20 15:01:34 | 显示全部楼层
    不错,只要有时间每天都会登陆支持一下!:lol
  • TA的每日心情
    恶心
    2015-11-23 14:20
  • 签到天数: 92 天

    [LV.6]常住居民II

    发表于 2015-6-18 08:56:11 | 显示全部楼层
    挺好的!!!!
    回复

    使用道具 举报

  • TA的每日心情
    犯困
    2015-1-11 14:36
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2015-6-26 15:19:34 | 显示全部楼层
    学习大神的思路

    该用户从未签到

    发表于 2016-7-6 10:23:56 | 显示全部楼层
    封装好一劳永逸
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-4-20 20:16 , Processed in 0.060258 second(s), 25 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表