iOS 一步步封装一个微信键盘

效果图:


键盘.gif

前言:要做成上面的效果图,需要我们自定义键盘。但是上面的键盘一个view 就可以搞定,可是下面的表情或者扩展怎么处理呢,有人说用UITextview的inputView 处理,可是在使用inpuview的时候,处理表情键盘或者扩展键盘,UITextview会一直成为响应者,光标会一直存在,所以我们把辅助键盘放在 下面。

如图:


说明.png
大概思路就是 点击键盘上UITextview的时候,让UITextview成为第一响应者,点击语音按钮,表情按钮,more 按钮,让UITextview取消第一响应者,然后把辅助键盘视图放置在键盘的下方。
1、 首先,我们自定义一个view,ChatBox。设置几种 键盘状态
typedef NS_ENUM(NSInteger, LXChatBoxStatus) {
    LXChatBoxStatusNothing,     // 默认状态
    LXChatBoxStatusShowVoLXe,   // 录音状态
    LXChatBoxStatusShowFace,    // 输入表情状态
    LXChatBoxStatusShowMore,    // 显示“更多”页面状态
    LXChatBoxStatusShowKeyboard,// 正常键盘
    LXChatBoxStatusShowVideo    // 录制视频
};

@property(nonatomic,assign)LXChatBoxStatus status;

在点击按钮或者 编辑UITextview的时候设置状态:
#pragma mark---textview--代理方法---
-(void)textViewDidBeginEditing:(UITextView *)textView{
    if (self.status != LXChatBoxStatusShowKeyboard) {
        self.status = LXChatBoxStatusShowKeyboard;

    }
        [self changeFrame:ceilf([textView sizeThatFits:textView.frame.size].height)];
}

#pragma mark---Event Responds---

-(void)voiceButtonDown:(UIButton *)button{
    
    button.selected = !button.selected;
    if (button.selected) {
        self.status = LXChatBoxStatusShowKeyboard;
    }else{
        self.status = LXChatBoxStatusShowVoLXe;
    }
    
}
-(void)faceButtonDown:(UIButton *)button{
    button.selected = !button.selected;
    if (button.selected) {
        self.status = LXChatBoxStatusShowFace;
    }else{
        self.status = LXChatBoxStatusShowKeyboard;
    }
   
    
}
-(void)moreButtonDown:(UIButton *)button{
    button.selected = !button.selected;
    if (button.selected) {
        self.status = LXChatBoxStatusShowMore;
    }else{
        self.status = LXChatBoxStatusShowKeyboard;
    }
}
通过设置键盘状态,在设置状态里对键盘视图的隐藏做一些处理。调整高度
-(void)setStatus:(LXChatBoxStatus)status{
    if (_status == status) {
        return;
    }
    _status = status;
    switch (_status) {
        case LXChatBoxStatusNothing:
        {
            self.voiceButton.selected = YES;
            self.faceView.hidden = self.moreView.hidden = YES;
            [self.textView resignFirstResponder];
            [UIView animateWithDuration:0.3 animations:^{
                self.frame = CGRectMake(0, KScreenH - self.textView.height - 2 *BOXTEXTViewSPACE, KScreenW, self.textView.height + 2 *BOXTEXTViewSPACE);

            }];
        }
            
           
            break;
        case LXChatBoxStatusShowKeyboard:
        {
            self.faceView.hidden = self.moreView.hidden = YES;

            self.voiceButton.selected = YES;
            self.textView.hidden = NO;
            self.talkButton.hidden = YES;
            self.faceButton.selected= NO;
            
            [UIView animateWithDuration:0.3 animations:^{
                self.frame = CGRectMake(0, self.y, KScreenW, self.textView.height + 2 *BOXTEXTViewSPACE);
                
            }];
             [self.textView becomeFirstResponder];
        }
        break;
        case LXChatBoxStatusShowVoLXe:
        {
            self.faceView.hidden = self.moreView.hidden = YES;

            [self.textView resignFirstResponder];
            self.voiceButton.selected = NO;
            self.talkButton.hidden = NO;
            self.textView.hidden = YES;
            [UIView animateWithDuration:0.3 animations:^{
                [self voiceResetFrame];
            }];

        }
            
            break;
        case LXChatBoxStatusShowFace:
        {
            if (self.textView.isFirstResponder) {
                [self.textView resignFirstResponder];
            }
            

            self.voiceButton.selected = YES;
            self.moreView.hidden = YES;
            self.faceView.hidden = NO;
            
            self.height = self.textView.height+2 *BOXTEXTViewSPACE + BOXOTHERH;
            self.y = KScreenH - self.height;
            self.bottomCotainer.y = self.textView.height + 2 *BOXTEXTViewSPACE;

        }
            
            break;
        case LXChatBoxStatusShowMore:
        {
            

            if (self.textView.isFirstResponder) {
                [self.textView resignFirstResponder];
            }
            
            self.voiceButton.selected = YES;
            self.moreView.hidden = NO;
            self.faceView.hidden = YES;

            self.height = self.textView.height+2 *BOXTEXTViewSPACE + BOXOTHERH;
            self.y = KScreenH - self.height;
            self.bottomCotainer.y = self.textView.height + 2 *BOXTEXTViewSPACE;
        }
        default:
            break;
    }
    if ([self.delegate respondsToSelector:@selector(changeStatusChat:)]) {
        [self.delegate changeStatusChat:self.y];
    }
}

2、但是,只是在状态里设置键盘高度是不够的,如果我们点击UITextview,执行顺序是这样的:

(1) -(void)keyboardWillChangeFrame:(NSNotification *)notification
(2) -(void)textViewDidBeginEditing:(UITextView *)textView

所以说,如果没有点击其他按钮(声音,表情,更多),点击了UITextview,在-(void)textViewDidBeginEditing:(UITextView *)textView设置键盘状态是没有用的,所以要键盘通知里做处理
-(void)keyboardWillChangeFrame:(NSNotification *)notification{
    
   
    //因为在 切换视图的时候,点击了表情按钮,或者更多按钮,输入框是,键盘弹出在textViewDidBeginEditing 这个方法调用之前就会调用,
//        self.height = self.textView.height + 2 *BOXTEXTViewSPACE;
    if (self.status == LXChatBoxStatusShowMore ||self.status == LXChatBoxStatusShowFace) {
        return;
    }
3、 针对键盘高度改变设置代理接口
@property(nonatomic,weak)id<LXChatBoxDelegate>delegate;
在键盘高度改变的地方设置代理(键盘状态改变得地方),(键盘Textview文字 改变的地方)(键盘通知),
 if ([self.delegate respondsToSelector:@selector(changeStatusChat:)]) {
        [self.delegate changeStatusChat:self.y];
    }

关于 接口:@property(nonatomic,assign)BOOL isDisappear;//为了在侧滑返回的时候自定义键盘与 键盘一体,可以参考文章:一体键盘
demo 地址:仿微信键盘

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

推荐阅读更多精彩内容

  • 2017.02.22 可以练习,每当这个时候,脑袋就犯困,我这脑袋真是神奇呀,一说让你做事情,你就犯困,你可不要太...
    Carden阅读 1,328评论 0 1
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,024评论 4 62
  • 文:吕一品 01 几年前,我有过一份工作,那时新来一个叫李娟的后生。第一年就成了我们公司的热点,大家都在议论她。 ...
    吕一品阅读 529评论 2 2
  • 以前上高中没觉得满课有什么不舒服,反而觉得很充实讨厌的星期五它天经地义。可是自从步入大学,感觉好多课特别是周二周五...
    丫丫孩纸啊阅读 391评论 2 2
  • 孩子心理教育特别重要,如果她自信,不轻易相信别人对她说的甜言蜜语,不轻易上当,就不会有这个故事。结局很感人,一位爸...
    美一天阅读 281评论 0 0