iOS 自定义数字和字母键盘

项目中有需求要实现自定义数字和字母键盘,照着网上的Demo敲了一下,效果图如下


IMG_4657.PNG

如图整个布局是三个UICollectionView , 数字和第一排字母是一个collectionView,从A到L是一个collectionView,最底部Z到M是一个collectionView。另外大小写切换按钮和删除按钮是额外加载自定义键盘上的。collectionView的CustomFlowLayout 参考之前的文章

使用方法:

KeyBoardView * KBView = [[KeyBoardView alloc]init];
TF.inputView = frameKBView;
KBView.inputSource = frameTF;

UICollectionViewCell是自定义的,定义一个Model用来显示键盘的大小写:

#import <Foundation/Foundation.h>

@interface KeyBoardModel : NSObject

@property (nonatomic,copy) NSString * key;

@property (nonatomic,assign) BOOL isUpper;

@end

自定义cell的.h文件实现

import <UIKit/UIKit.h>

#import "KeyBoardModel.h"

@protocol KeyBoardCellDelegate <NSObject>

@optional
- (void)KeyBoardCellBtnClick:(NSInteger)Tag;

@end

@interface KeyBoardCell : UICollectionViewCell

@property (nonatomic,weak) id <KeyBoardCellDelegate> delegate;

@property (nonatomic,strong) UIButton * keyboardBtn;

@property (nonatomic,strong) KeyBoardModel * model;

@end

自定义cell的.m实现

#import "KeyBoardCell.h"

@implementation KeyBoardCell

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

- (void)setup
{
    [self keyboardBtn];
}

- (UIButton *)keyboardBtn
{
    if (!_keyboardBtn)
    {
        _keyboardBtn = [UIButton new];
        [_keyboardBtn setBackgroundImage:[UIImage imageNamed:@"keyboard_key"] forState:UIControlStateNormal];
        [_keyboardBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_keyboardBtn addTarget:self action:@selector(KeyboardBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:_keyboardBtn];
        _keyboardBtn.frame = self.contentView.bounds;
    }
    return _keyboardBtn;
}

- (void)KeyboardBtnClick:(UIButton *)sender
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(KeyBoardCellBtnClick:)])
    {
        [self.delegate KeyBoardCellBtnClick:self.tag - 100];
    }
}

- (void)setModel:(KeyBoardModel *)model
{
    if (_model != model)
    {
        _model = model;
        
        if(!model.isUpper && self.tag > 9 + 100)
        {
            NSString * string = [model.key lowercaseString];
            
            [self.keyboardBtn setTitle:string forState:UIControlStateNormal];
        }
        else
        {
            [self.keyboardBtn setTitle:model.key forState:UIControlStateNormal];
        }
    }
}

自定义键盘视图的.h实现

#import <UIKit/UIKit.h>

#import "KeyBoardCell.h"
#import "CustomFlowLayout.h"

@interface KeyBoardView : UIView <UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,KeyBoardCellDelegate>

{
    BOOL isUp;
}


@property (nonatomic,strong) UICollectionView * topView;

@property (nonatomic,strong) UICollectionView * middleView;

@property (nonatomic,strong) UICollectionView * bottomView;

@property (nonatomic,strong) UIView * inputSource;

@property (nonatomic,strong) UIButton * clearBtn;

@property (nonatomic,strong) UIButton * upBtn;

@property (nonatomic,strong) NSMutableArray * modelArray;

@property (nonatomic,strong) NSArray * letterArray;

@end

自定义键盘的.m实现

#import "KeyBoardView.h"

#define SCREEN_WIDTH         [UIScreen mainScreen].bounds.size.width

#define BOARDRATIO           (224.0 / 275)           //键盘的高宽比
#define KEYRATIO             (86.0  / 63)            //按键的高宽比

#define KEYBOARD_HEIGHT      (SCREEN_WIDTH * BOARDRATIO)    //键盘的高

#define BTN_WIDTH            (SCREEN_WIDTH / 10.0 - 6) //按键的宽
#define BTN_HEIGHT           (BTN_WIDTH * KEYRATIO)         //按键的高
#define ITEM_HEIGHT          (BTN_HEIGHT + 10)              //item的高

#define TOTAL_HEIGHT         (ITEM_HEIGHT * 4 + 10)

@implementation KeyBoardView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.frame = CGRectMake(0, 0, SCREEN_WIDTH, TOTAL_HEIGHT);
        
        [self setData];
        [self setup];
    }
    return self;
}

- (void)setData
{
    isUp = YES;
    
    for (NSInteger i = 1 ; i < 10 ; i ++)
    {
        KeyBoardModel * model = [KeyBoardModel new];
        model.isUpper = YES;
        model.key = [NSString stringWithFormat:@"%ld",i];
        [self.modelArray addObject:model];
    }
    
    KeyBoardModel * model = [KeyBoardModel new];
    model.isUpper = YES;
    model.key = @"0";
    [self.modelArray addObject:model];
    
    for (NSInteger i = 0 ; i < 26 ; i ++ )
    {
        KeyBoardModel * model = [KeyBoardModel new];
        model.isUpper = YES;
        model.key = self.letterArray[i];
        
        [self.modelArray addObject:model];
    }
}

- (NSMutableArray *)modelArray
{
    if (!_modelArray)
    {
        _modelArray = [NSMutableArray new];
    }
    return _modelArray;
}

- (NSArray *)letterArray
{
    if (!_letterArray)
    {
        _letterArray = [NSArray arrayWithObjects:@"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", nil];
    }
    return _letterArray;
}

- (UIButton *)clearBtn
{
    if (!_clearBtn)
    {
        _clearBtn = [UIButton new];
        [_clearBtn setImage:[UIImage imageNamed:@"clear_a"] forState:UIControlStateNormal];
        [_clearBtn setImage:[UIImage imageNamed:@"clear_b"] forState:UIControlStateHighlighted];
        [_clearBtn addTarget:self action:@selector(ClearBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_clearBtn];
        [_clearBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.right.equalTo(self).offset(-3);
            make.bottom.mas_equalTo(-10);
            make.size.mas_equalTo(CGSizeMake(BTN_HEIGHT, BTN_HEIGHT));
        }];
    }
    return _clearBtn;
}

- (UIButton *)upBtn
{
    if (!_upBtn)
    {
        _upBtn = [UIButton new];
        [_upBtn setImage:[UIImage imageNamed:@"up_a"] forState:UIControlStateNormal];
        [_upBtn setImage:[UIImage imageNamed:@"up_b"] forState:UIControlStateHighlighted];
        [_upBtn addTarget:self action:@selector(UpBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_upBtn];
        [_upBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self).offset(3);
            make.bottom.mas_equalTo(-10);
            make.size.mas_equalTo(CGSizeMake(BTN_HEIGHT, BTN_HEIGHT));
        }];
    }
    return _upBtn;
}

- (void)setup
{
    self.backgroundColor = RGBA(255, 192, 0, 1);
    
    [self upBtn];
    [self clearBtn];

    //topView
    CustomFlowLayout * topflowLayout = [[CustomFlowLayout alloc]init];
    topflowLayout.sectionInset = UIEdgeInsetsMake(10, 3, 0, 3);
    [topflowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    
    self.topView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH , ITEM_HEIGHT * 2) collectionViewLayout:topflowLayout];
    [self addSubview:self.topView];
    self.topView.delegate = self;
    self.topView.dataSource = self;
    self.topView.backgroundColor = [UIColor clearColor];
    [self.topView registerClass:[KeyBoardCell class] forCellWithReuseIdentifier:NSStringFromClass([KeyBoardCell class])];
    
    
    //middleView
    CustomFlowLayout * middleflowLayout = [[CustomFlowLayout alloc]init];
    middleflowLayout.sectionInset = UIEdgeInsetsMake(10, 3, 0, 3);
    [middleflowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];

    self.middleView = [[UICollectionView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH / 20.0, ITEM_HEIGHT * 2, SCREEN_WIDTH / 10.0 * 9, ITEM_HEIGHT) collectionViewLayout:middleflowLayout];
    [self addSubview:self.middleView];
    self.middleView.delegate = self;
    self.middleView.dataSource = self;
    self.middleView.backgroundColor = [UIColor clearColor];
    [self.middleView registerClass:[KeyBoardCell class] forCellWithReuseIdentifier:NSStringFromClass([KeyBoardCell class])];
    
    //bottomView
    CustomFlowLayout * bottomflowLayout = [[CustomFlowLayout alloc]init];
    bottomflowLayout.sectionInset = UIEdgeInsetsMake(10, 3, 0, 3);
    [bottomflowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    
    self.bottomView = [[UICollectionView alloc]initWithFrame:CGRectMake(SCREEN_WIDTH * 3.0 / 20.0, ITEM_HEIGHT * 3, SCREEN_WIDTH / 10.0 * 7.0, ITEM_HEIGHT) collectionViewLayout:bottomflowLayout];
    [self addSubview:self.bottomView];
    self.bottomView.delegate = self;
    self.bottomView.dataSource = self;
    self.bottomView.backgroundColor = [UIColor clearColor];
    [self.bottomView registerClass:[KeyBoardCell class] forCellWithReuseIdentifier:NSStringFromClass([KeyBoardCell class])];
    
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    if (collectionView == self.topView)
    {
        return 2;
    }
    
    if (collectionView == self.middleView)
    {
        return 1;
    }
    
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    if (collectionView == self.topView)
    {
        return 10;
    }
    
    if (collectionView == self.middleView)
    {
        return 9;
    }
    
    return 7;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //重用cell
    KeyBoardCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([KeyBoardCell class]) forIndexPath:indexPath];
    
    NSInteger index = indexPath.section * 10 + indexPath.item ;
    if (collectionView == self.middleView)
    {
        index = 20 + indexPath.section * 10 + indexPath.item ;
    }
    else if (collectionView == self.bottomView)
    {
        index = 29 + indexPath.section * 10 + indexPath.item ;
    }
    cell.tag = index + 100;
    cell.delegate = self;
    KeyBoardModel * model = (KeyBoardModel *)[self.modelArray objectAtIndex:index];
    KeyBoardModel * newmodel = [KeyBoardModel new];
    newmodel.key = model.key;
    newmodel.isUpper = isUp;
    
    cell.model = newmodel;
    return cell;
}

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(BTN_WIDTH , BTN_HEIGHT);
}

#pragma mark - 设置每个UICollectionView最小垂直间距

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}

#pragma mark - 设置每个UICollectionView最小水平间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}


#pragma mark - KeyBoardCellDelgate
- (void)KeyBoardCellBtnClick:(NSInteger)Tag
{
    KeyBoardModel * model = (KeyBoardModel *)[self.modelArray objectAtIndex:Tag];
    if (!isUp && Tag > 9)
    {
        NSString * string = [model.key lowercaseString];
        [self inputString:string];
    }
    else
    {
        [self inputString:model.key];
    }
}

#pragma mark - Response Events
- (void)UpBtnClick:(UIButton *)sender
{
    sender.userInteractionEnabled = NO;
    isUp = !isUp;
    UIImage * image = isUp ? [UIImage imageNamed:@"up_a"] : [UIImage imageNamed:@"up_b"];
    [sender setImage:image forState:UIControlStateNormal];
    
    [self.topView reloadData];
    [self.middleView reloadData];
    [self.bottomView reloadData];
    sender.userInteractionEnabled = YES;
}

- (void)ClearBtnClick:(UIButton *)sender
{
    if (self.inputSource)
    {
        if ([self.inputSource isKindOfClass:[UITextField class]])
        {
            UITextField *tmp = (UITextField *)self.inputSource;
            [tmp deleteBackward];
        }
        else if ([self.inputSource isKindOfClass:[UITextView class]])
        {
            UITextView *tmp = (UITextView *)self.inputSource;
            [tmp deleteBackward];
        }
        else if ([self.inputSource isKindOfClass:[UISearchBar class]])
        {
            UISearchBar *tmp = (UISearchBar *)self.inputSource;
            NSMutableString *info = [NSMutableString stringWithString:tmp.text];
            if (info.length > 0) {
                NSString *s = [info substringToIndex:info.length-1];
                [tmp setText:s];
            }
        }
    }
}

#pragma mark - Private Events
- (void)inputString:(NSString *)string
{
    if (self.inputSource)
    {
        //UITextField
        if ([self.inputSource isKindOfClass:[UITextField class]])
        {
            UITextField * tmp = (UITextField *)self.inputSource;
            if (tmp.delegate && [tmp.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)])
            {
                NSRange range = NSMakeRange(tmp.text.length, 1);
                BOOL ret = [tmp.delegate textField:tmp shouldChangeCharactersInRange:range replacementString:string];
                if (ret)
                {
                    [tmp insertText:string];
                }
            }
            else
            {
                [tmp insertText:string];
            }
            
        }
        
        //UITextView
        else if ([self.inputSource isKindOfClass:[UITextView class]])
        {
            UITextView * tmp = (UITextView *)self.inputSource;
            if (tmp.delegate && [tmp.delegate respondsToSelector:@selector(textView:shouldChangeTextInRange:replacementText:)])
            {
                NSRange range = NSMakeRange(tmp.text.length, 1);
                BOOL ret = [tmp.delegate textView:tmp shouldChangeTextInRange:range replacementText:string];
                if (ret)
                {
                    [tmp insertText:string];
                }
            }
            else
            {
                [tmp insertText:string];
            }
            
        }
        
        //UISearchBar
        else if ([self.inputSource isKindOfClass:[UISearchBar class]])
        {
            UISearchBar *tmp = (UISearchBar *)self.inputSource;
            NSMutableString * info = [NSMutableString stringWithString:tmp.text];
            [info appendString:string];
            if (tmp.delegate && [tmp.delegate respondsToSelector:@selector(searchBar:shouldChangeTextInRange:replacementText:)])
            {
                NSRange range = NSMakeRange(tmp.text.length, 1);
                BOOL ret = [tmp.delegate searchBar:tmp shouldChangeTextInRange:range replacementText:string];
                if (ret)
                {
                    [tmp setText:[info copy]];
                }
            }
            else
            {
                [tmp setText:[info copy]];
            }
        }
    }
}

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

推荐阅读更多精彩内容