当UITextFiled和UITextView这种文本输入类控件成为第一响应者时,弹出的键盘由他们的一个UIView类的inputView属性来控制,当inputView为nil时会弹出系统的键盘,想要弹出自定义的键盘,将我们自定义的UIView对象给inputView属性赋值即可。表情键盘重点在于排列各个表情和删除键,以及表情键盘上的各种回调设置;

下面为键盘预览图,兼容了竖屏各版本适配,横屏没有兼顾。横屏适配参见这篇博客iOS之自定义表情键盘

图1为6的常用表情,图2为6的全部表情,图3为5的全部表情,表情个数统一为7列3排,根据屏幕不同修改间距以及键盘高度;

    

下面为项目结构图:采用MVC模式,View层提供表情键盘以及自定义的UITextView。Model层提供表情数据。我为了简单就直接把聊天工具栏通过storyboard拖到了VC上,这里应该再封装一个toolView的;

1、首先来弄好数据层FaceManager,具有一个单例方法、声明了三个数组属性来存放不同的表情;表情图片由Face文件夹来提供;

AllFaces通过我一个名为“emoticons”的plist文件来获取,里面存放的是一个个表情字典,对应着Face中的图片名和图片文字描述;

RecentlyFaces是最近使用过的图片,从本地获取;BigFaces是用来扩展其他大型以及动态效果表情的,没有实现

 1 @interface FacesManager : NSObject
 2
 3 @property (nonatomic, strong, readonly)NSArray * RecentlyFaces;
 4 @property (nonatomic, strong, readonly)NSArray * AllFaces;
 5 @property (nonatomic, strong, readonly)NSArray * BigFaces;
 6
 7 + (instancetype)share;
 8 - (void)fetchRecentlyFaces;
 9 @end
10
11 #import "FacesManager.h"
12
13 @implementation FacesManager
14
15 +(instancetype)share
16 {
17     static FacesManager * m = nil;
18     static dispatch_once_t onceToken;
19     dispatch_once(&onceToken, ^{
20         m = [[FacesManager alloc] init];
21     });
22     return m ;
23 }
24
25 - (instancetype)init
26 {
27     self = [super init];
28     if (self) {
29         [self fetchAllFaces];
30         [self fetchBigFaces];
31     }
32     return self;
33 }
34
35 - (void)fetchAllFaces
36 {
37     NSString * path = [[NSBundle mainBundle] pathForResource:@"emoticons" ofType:@"plist"];
38     NSArray * arrFace = [NSArray arrayWithContentsOfFile:path];
39     _AllFaces = arrFace;
40 }
41
42 - (void)fetchRecentlyFaces
43 {
44     NSUserDefaults * defauls = [NSUserDefaults standardUserDefaults];
45     NSArray * arrFace = [defauls objectForKey:@"RecentlyFaces"];
46     _RecentlyFaces = arrFace;
47 }
48
49 - (void)fetchBigFaces
50 {
51
52 }
53
54 @end

View Code

 

2、数据层弄好后,实现关键的FaceKeyBoardView;首先在这个view上我们需要向外发送:点击每个表情、发送键、删除键的事件,所以需要提供三个向外的回调接口:点击表情的回调、点击删除的回调、点击发送的回调;然后再分析视图结构,首先view上部贴了一个ScrollView用来滑动显示每一页表情、一个稍微靠下的的pageController用于显示当前页数、以及底部的toolBar;

FaceKeyBoardView.h

define了几个需要用到的参数。设置了三个回调接口;

 1 #import <UIKit/UIKit.h>
 2 #define GrayColor [UIColor colorWithRed:231 / 255.0 green:231 / 255.0 blue:231 / 255.0 alpha:1]
 3 #define ScreenWidth [UIScreen mainScreen].bounds.size.width
 4 #define ScreenHeight [UIScreen mainScreen].bounds.size.height
 5 #define ToolBarHeight 40
 6
 7 typedef void (^FaceKeyBoardBlock)(NSString * faceName,NSInteger faceTag);
 8 typedef void (^FaceKeyBoardSendBlock)(void);
 9 typedef void (^FaceKeyBoardDeleteBlock)(void);
10
11 @interface FaceKeyBoardView : UIView
12
13 - (void)setFaceKeyBoardBlock:(FaceKeyBoardBlock)block;
14 - (void)setFaceKeyBoardSendBlock:(FaceKeyBoardSendBlock)block;
15 - (void)setFaceKeyBoardDeleteBlock:(FaceKeyBoardDeleteBlock)block;
16 @end

View Code

FaceKeyBoardView.m:

用到的属性:

 1 @interface FaceKeyBoardView ()<UIScrollViewDelegate>
 2
 3 {
 4     CGFloat _FKBViewH;
 5 }
 6
 7 @property (nonatomic, strong)NSArray * arrFace;
 8 @property (nonatomic, strong)UIScrollView * scFace;
 9 @property (nonatomic, strong)FaceKeyBoardBlock block;
10 @property (nonatomic, strong)FaceKeyBoardSendBlock sendBlock;
11 @property (nonatomic, strong)FaceKeyBoardDeleteBlock deleteBlock;
12 @property (nonatomic, strong)UIToolbar * toolBar;
13 @property (nonatomic, strong)UIPageControl * pageC;
14
15 @property (nonatomic, strong)FacesManager * FManager;
16
17 @end

View Code

a、首先来重写view的init方法,在这里面设定好view的frame以及设定view的子控件。由于屏幕尺寸不同,所以表情竖直方向间距不同,就会影响到表情键盘的高度,所以frame是动态计算出来的;然后再loadview方法中初始化facemanager用来提供数据,以及获得全部表情和设置toolBar;

 1 - (instancetype)init
 2 {
 3     self = [super init];
 4     if (self) {
 5         [self setViewFrame];
 6         [self loadKeyBoardView];
 7     }
 8     return self;
 9 }
10
11 - (void)setViewFrame
12 {
13     CGFloat marginY = (ScreenWidth - 7 * 30) / (7 + 1);
14     CGFloat scViewH = 3 * (30 + marginY) + marginY*2 + 10;
15     _FKBViewH = scViewH + ToolBarHeight;
16     self.frame = CGRectMake(0, ScreenHeight - _FKBViewH, ScreenWidth, _FKBViewH);
17 }
18
19 - (void)loadKeyBoardView
20 {
21     //初始化manager
22     self.FManager = [FacesManager share];
23     //获取数据
24     [self fetchAllFaces];
25     //设置toolBar
26     [self setToolBar];
27 }

View Code

b、设置了三个方法来获取不同的表情数据用于显示不同的表情键盘;第一次时默认执行fetchAllFaces;

 1 - (void)fetchRecentlyFaces
 2 {
 3     //更新manager
 4     [self.FManager fetchRecentlyFaces];
 5     self.arrFace = self.FManager.RecentlyFaces;
 6     [self setFaceFrame];
 7 }
 8
 9 - (void)fetchAllFaces
10 {
11     self.arrFace = self.FManager.AllFaces;
12     //设置表情scrollView
13     [self setFaceFrame];
14 }
15
16 - (void)fetchBigFaces
17 {
18     self.arrFace = nil;
19     [self setFaceFrame];
20 }

View Code

 

c、在setFaceFrame方法中设置scrollView以及pageController;我通过表情数量来循环设置每个表情按钮的位置,固定了7列三行,根据屏幕设置不同的间距,在每一页的右下角设置删除按钮。根据页数来设置scrollView的内容宽度以及pageController的页数;

 1 - (void)setFaceFrame
 2 {
 3     //列数
 4     NSInteger colFaces = 7;
 5     //行数
 6     NSInteger rowFaces = 3;
 7     //设置face按钮frame
 8     CGFloat FaceW = 30;
 9     CGFloat FaceH = 30;
10     CGFloat marginX = (ScreenWidth - colFaces * FaceW) / (colFaces + 1);
11     CGFloat marginY = marginX;
12     NSLog(@"%lf",marginX);
13
14     //表情数量
15     NSInteger FaceCount = self.arrFace.count;
16     //每页表情数和scrollView页数;
17     NSInteger PageFaceCount = colFaces * rowFaces ;
18     NSInteger SCPages = FaceCount / PageFaceCount + 1;
19
20     CGFloat scViewH = rowFaces * (FaceH + marginY) + marginY*2 + 10;
21     //初始化scrollView
22     self.scFace = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, scViewH)];
23     self.scFace.contentSize = CGSizeMake(ScreenWidth * SCPages, scViewH);
24     self.scFace.pagingEnabled = YES;
25     self.scFace.bounces = NO;
26     self.scFace.delegate = self;
27     [self addSubview:self.scFace];
28     //初始化贴在sc上的view
29     UIView * BtnView = [[UIView alloc] init];
30     BtnView.frame = CGRectMake(0, 0, ScreenWidth * SCPages, scViewH);
31     [BtnView setBackgroundColor:GrayColor];
32     [self.scFace addSubview:BtnView];
33
34     for (NSInteger i = 0; i < FaceCount + SCPages; i ++)
35     {
36         //当前页数
37         NSInteger currentPage = i / PageFaceCount;
38         //当前行
39         NSInteger rowIndex = i / colFaces - (currentPage * rowFaces);
40         //当前列
41         NSInteger colIndex = i % colFaces;
42
43         //viewW * currentPage换页
44         CGFloat btnX = marginX + colIndex * (FaceW + marginX) + ScreenWidth * currentPage;
45         CGFloat btnY = rowIndex * (marginY + FaceH) + marginY;
46         if ((i - (currentPage + 1) * (PageFaceCount - 1) == currentPage || i == FaceCount + SCPages - 1) && self.arrFace)
47         {
48             //创建删除按钮
49             CGFloat btnDelteX = (currentPage + 1) * ScreenWidth - (marginX + FaceW);
50             CGFloat btnDelteY = 2 * (FaceH + marginY) +marginY;
51
52             UIButton * btnDelte = [UIButton buttonWithType:UIButtonTypeSystem];
53             btnDelte.frame = CGRectMake(btnDelteX, btnDelteY, FaceW, FaceH);
54             [btnDelte setBackgroundImage:[UIImage imageNamed:@"icon_delete-2"] forState:UIControlStateNormal];
55             [btnDelte setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
56             btnDelte.titleLabel.font = [UIFont boldSystemFontOfSize:15];
57
58             [btnDelte addTarget:self action:@selector(tapDeleteBtn) forControlEvents:UIControlEventTouchUpInside];
59
60             [BtnView addSubview:btnDelte];
61         }
62         else
63         {
64         //创建face按钮
65         UIButton * btn = [[UIButton alloc] init];
66         btn.frame = CGRectMake(btnX , btnY, FaceW, FaceH);
67         //tga
68         btn.tag = i - currentPage;
69         //按钮回调;
70         [btn addTarget:self action:@selector(tapFaceBtnWithButton:) forControlEvents:UIControlEventTouchUpInside];
71         NSString * strIMG = self.arrFace[i - currentPage][@"png"];
72         [btn setImage:[UIImage imageNamed:strIMG] forState:UIControlStateNormal];
73         [BtnView addSubview:btn];
74         }
75     }
76
77     //创建pageController
78     CGFloat pageH = 10;
79     CGFloat pageW = ScreenWidth;
80     CGFloat pageX = 0;
81     CGFloat pageY = scViewH - pageH - marginY;
82     self.pageC = [[UIPageControl alloc] initWithFrame:CGRectMake(pageX, pageY, pageW, pageH)];
83     self.pageC.numberOfPages = SCPages;
84     self.pageC.currentPage = 0;
85     self.pageC.pageIndicatorTintColor = [UIColor lightGrayColor];
86     self.pageC.currentPageIndicatorTintColor = [UIColor grayColor];
87     [self addSubview:self.pageC];
88 }

View Code

b、还需要把c中的各种点击事件和scrollView的代理事件实现
点击表情的事件中我执行了2个操作:1、将点击的表情存到本地常用表情数组中,逻辑为,如果数组中已有这个表情,就将此表情移到最前面,没有就将表情插入到数组第一位。这里我想着数据量不是很大就使用了Preference来存放本地;2、将表情的文字描述和表情按钮的tga通过block传出去;

当scrollView翻动时,让pageController的当前页数跟着变化;点击删除发送回调;

 1 //点击表情
 2 - (void)tapFaceBtnWithButton:(UIButton *)button
 3 {
 4     //将表情存储为常用表情
 5     NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
 6     NSMutableArray * arrFaces = (NSMutableArray *)[defaults objectForKey:@"RecentlyFaces"];
 7
 8     if (!arrFaces)
 9     {
10         arrFaces = [NSMutableArray array];
11         NSDictionary * dicFace = @{@"png":self.arrFace[button.tag][@"png"],@"faceTag":@(button.tag),@"chs":self.arrFace[button.tag][@"chs"]};
12         [arrFaces addObject:dicFace];
13         [defaults setObject:arrFaces forKey:@"RecentlyFaces"];
14         [defaults synchronize];
15     }
16     //NSLog(@"%p",arrFaces);
17     else
18     {
19         //需要新建一个可变数组,不然修改数组会报错。
20         NSMutableArray * arrM = [NSMutableArray arrayWithArray:arrFaces];
21         BOOL isHaveSameFace = NO;
22         for (NSDictionary * dic in arrFaces)
23         {
24             //NSLog(@"%ld--%ld",button.tag,[dic[@"faceTag"] integerValue]);
25             NSString * strFace = self.arrFace[button.tag][@"chs"];
26             NSString * strFaceDic = dic[@"chs"];
27             if ([strFace isEqualToString:strFaceDic])
28             {
29                 [arrM removeObject:dic];
30                 NSLog(@"%@",dic);
31                 //后添加的排在前面;
32                 [arrM insertObject:dic atIndex:0];
33                 isHaveSameFace = YES;
34             }
35         }
36         if (!isHaveSameFace)
37         {
38             NSDictionary * dicFace = @{@"png":self.arrFace[button.tag][@"png"],@"faceTag":@(button.tag),@"chs":self.arrFace[button.tag][@"chs"]};
39             [arrM insertObject:dicFace atIndex:0];
40         }
41         [defaults setObject:arrM forKey:@"RecentlyFaces"];
42         [defaults synchronize];
43     }
44     //block传值
45     self.block(self.arrFace[button.tag][@"chs"],button.tag);
46 }
47
48 //点击删除
49 - (void)tapDeleteBtn
50 {
51     self.deleteBlock();
52 }
53
54 -(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
55 {
56     self.pageC.currentPage = targetContentOffset->x / ScreenWidth;
57 }

View Code

d、设置toolBar、然后将各个按钮的点击事件实现:

 1 - (void)setToolBar
 2 {
 3     self.toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.scFace.frame.size.height, ScreenWidth, ToolBarHeight)];
 4     self.toolBar.backgroundColor = GrayColor;
 5
 6     [self addSubview:self.toolBar];
 7     UIBarButtonItem * spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
 8     UIBarButtonItem * recentlyFaceItem = [[UIBarButtonItem alloc] initWithTitle:@"最近表情" style:UIBarButtonItemStylePlain target:self action:@selector(tapRecentlyFaceBtn)];
 9     UIBarButtonItem * normalFaceItem = [[UIBarButtonItem alloc] initWithTitle:@"普通" style:UIBarButtonItemStylePlain target:self action:@selector(tapNormalFaceBtn)];
10     UIBarButtonItem * bigFaceItem = [[UIBarButtonItem alloc] initWithTitle:@"大表情" style:UIBarButtonItemStylePlain target:self action:@selector(tapBigFaceBtn)];
11     UIBarButtonItem * sendItem = [[UIBarButtonItem alloc] initWithTitle:@"发送" style:UIBarButtonItemStylePlain target:self action:@selector(tapSendBtn)];
12
13     [self.toolBar setItems:[NSArray arrayWithObjects:recentlyFaceItem,spaceItem,normalFaceItem,spaceItem,bigFaceItem,spaceItem,sendItem, nil]];
14 }
15
16
17 //点击ToolBar上的按钮回调
18 - (void)tapRecentlyFaceBtn
19 {
20     [self fetchRecentlyFaces];
21 }
22 - (void)tapSendBtn
23 {
24     self.sendBlock();
25 }
26 - (void)tapBigFaceBtn{
27     [self fetchBigFaces];
28 }
29 - (void)tapNormalFaceBtn
30 {
31     [self fetchAllFaces];
32 }

View Code

e、还要实现三个设置回调接口的方法、此时faceKeyBoardView中的方法都实现了;

 1 //点击表情接口
 2 - (void)setFaceKeyBoardBlock:(FaceKeyBoardBlock)block
 3 {
 4     self.block = block;
 5 }
 6 //发送接口
 7 -(void)setFaceKeyBoardSendBlock:(FaceKeyBoardSendBlock)block
 8 {
 9     self.sendBlock = block;
10 }
11 //删除接口
12 -(void)setFaceKeyBoardDeleteBlock:(FaceKeyBoardDeleteBlock)block
13 {
14     self.deleteBlock = block;
15 }

View Code

3、自定义一个UITextView、也可以使用UITextFiledView

.h:具有一个发送回调以及切换键盘状态的方法:

1 #import "XQGTextView.h"
2 #import "FaceKeyBoardView.h"
3
4 @interface XQGTextView ()
5
6 @property (nonatomic, strong)FaceKeyBoardView * viewFaceKB;
7 @property (nonatomic, strong)SendBlock block;
8 @end

View Code

.m:实现方法以及初始化表情键盘,在faceKeyBoard发送回调和删除回调中实现需要做的事;

 1 @implementation XQGTextView
 2
 3 - (instancetype)initWithFrame:(CGRect)frame
 4 {
 5     self = [super initWithFrame:frame];
 6     if (self) {
 7         [self loadFaceKeyBoardView];
 8     }
 9     return self;
10 }
11
12 - (void)awakeFromNib
13 {
14     [self loadFaceKeyBoardView];
15 }
16
17 - (void)loadFaceKeyBoardView
18 {
19     self.viewFaceKB = [[FaceKeyBoardView alloc] init];
20
21     __weak __block XQGTextView * copy_self = self;
22
23     [self.viewFaceKB setFaceKeyBoardBlock:^(NSString *faceName, NSInteger faceTag) {
24         copy_self.text = [copy_self.text stringByAppendingString:faceName];
25     }];
26
27     [self.viewFaceKB setFaceKeyBoardSendBlock:^{
28         copy_self.block();
29         //清空textview
30         copy_self.text = nil;
31     }];
32     [self.viewFaceKB setFaceKeyBoardDeleteBlock:^{
33         NSMutableString * string = [[NSMutableString alloc] initWithString:copy_self.text];
34         [string deleteCharactersInRange:NSMakeRange(copy_self.text.length - 1, 1)];
35         copy_self.text = string;
36     }];
37 }
38
39 -(void)changeKeyBoard
40 {
41     if (self.inputView != nil)
42     {
43         self.inputView = nil;
44         [self reloadInputViews];
45     }
46     else
47     {
48         self.inputView = self.viewFaceKB;
49         [self reloadInputViews];
50     }
51 }
52
53 - (void)setFaceKeyBoard
54 {
55     self.inputView = self.viewFaceKB;
56 }
57
58 - (void)setSendBlock:(SendBlock)block
59 {
60     self.block = block;
61 }
62
63 @end

View Code

4、在VC中进行操作:

a、在storyBoard中构建聊天工具栏:将textView绑定为我自定义的textView;

b、在发送回调中进行发送消息,利用正则表达式解析出表情发送图文混排的消息;以及聊天工具栏跟随键盘高度变化而变化的设置等;点击表情按钮弹出表情键盘,键盘切换;代码中都有详细描述;

.m:

  1 #import "MainViewController.h"
  2 #import "XQGTextView.h"
  3
  4 @interface MainViewController ()<UITextViewDelegate>
  5
  6 @property (weak, nonatomic) IBOutlet XQGTextView *viewText;
  7 @property (weak, nonatomic) IBOutlet UIView *viewChatToolBar;
  8 @property (weak, nonatomic) IBOutlet UILabel *lalText;
  9
 10 @end
 11
 12 @implementation MainViewController
 13
 14 - (void)viewDidLoad {
 15     [super viewDidLoad];
 16     //清空常用表情
 17 //    NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
 18 //    NSMutableArray * arrFaces = [defaults objectForKey:@"RecentlyFaces"];
 19 //    arrFaces = nil;
 20 //    [defaults setObject:arrFaces forKey:@"RecentlyFaces"];
 21
 22     self.viewText.delegate = self;
 23     //发送回调
 24     [self.viewText setSendBlock:^{
 25         [self sendPictureAndText];
 26     }];
 27     //监听键盘弹出的通知
 28     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
 29     [center addObserver:self selector:@selector(KeyBoardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
 30 }
 31
 32 //发送图文
 33 - (void)sendPictureAndText
 34 {
 35     //正则表达式取出表情
 36     NSString * str = self.viewText.text;
 37     NSMutableAttributedString * strAtt = [[NSMutableAttributedString alloc] initWithString:str];
 38     //创建匹配正则表达式类型描述模板
 39     NSString * pattern = @"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]";
 40     //依据正则表达式创建匹配对象
 41     NSError * error = nil;
 42     //CaseInsensitive
 43     NSRegularExpression * regular = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
 44     if (regular == nil)
 45     {
 46         NSLog(@"正则创建失败");
 47         NSLog(@"%@",error.localizedDescription);
 48         return;
 49     }
 50     //把搜索出来的结果存到数组中
 51     NSArray * result = [regular matchesInString:strAtt.string options:NSMatchingReportCompletion range:NSMakeRange(0, strAtt.string.length)];
 52
 53     NSString * path = [[NSBundle mainBundle] pathForResource:@"emoticons.plist" ofType:nil];
 54     NSArray * arrPlist = [NSArray arrayWithContentsOfFile:path];
 55
 56     for (NSInteger i = result.count - 1; i >= 0; i--)
 57     {
 58         NSTextCheckingResult * r = result[i];
 59         //NSLog(@"%@",NSStringFromRange(r.range));
 60         NSString * imageStr = [strAtt.string substringWithRange:r.range];
 61         //NSLog(@"%@",imageStr);
 62
 63         for (NSDictionary * dic in arrPlist)
 64         {
 65             if ([dic[@"chs"] isEqualToString:imageStr])
 66             {
 67                 NSTextAttachment * textAtt = [[NSTextAttachment alloc] init];
 68                 textAtt.image = [UIImage imageNamed:dic[@"png"]];
 69                 NSAttributedString * strImage = [NSAttributedString attributedStringWithAttachment:textAtt];
 70                 [strAtt replaceCharactersInRange:r.range withAttributedString:strImage];
 71             }
 72         }
 73     }
 74     self.lalText.attributedText = strAtt;
 75 }
 76
 77 //监听键盘弹出的方法
 78 -(void)KeyBoardWillChangeFrame: (NSNotification *)noteInfo
 79 {
 80     //获取键盘的Y值
 81     CGRect keySize = [noteInfo.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
 82     CGFloat keyY = keySize.origin.y;
 83     //让view跟随键盘移动
 84     CGFloat viewY = keyY - self.view.bounds.size.height;
 85     //让view变化和键盘变化一致
 86     self.view.transform = CGAffineTransformMakeTranslation(0, viewY);
 87 }
 88
 89 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 90 {
 91     UITouch * touch = [touches anyObject];
 92     if ([touch.view isEqual:self.view]) {
 93         [self.view endEditing:YES];
 94     }
 95 }
 96 //监控编辑结束状态
 97 -(void)textViewDidEndEditing:(UITextView *)textView
 98 {
 99     self.viewText.inputView = nil;
100 }
101
102
103 - (IBAction)tapVoice:(UIButton *)sender {
104     NSLog(@"切换语音");
105 }
106
107 - (IBAction)tapFace:(UIButton *)sender
108 {
109     //如果还没弹出键盘就直接弹出表情键盘;弹出了就改变键盘样式
110     if (self.viewText.isFirstResponder)
111     {
112         [self.viewText changeKeyBoard];
113     }
114     else
115     {
116         [self.viewText setFaceKeyBoard];
117         [self.viewText becomeFirstResponder];
118     }
119 }
120
121 - (IBAction)tapMoreFunction:(UIButton *)sender {
122     NSLog(@"更多功能");
123 }
124
125
126 @end

View Code

这样,自定义表情键盘就实现了,聊天工具栏还需要进行进一步的封装;

转载于:https://www.cnblogs.com/xiaoqiuge/p/4858057.html

iOS_仿QQ表情键盘相关推荐

  1. Android开发之仿QQ表情实现(上)

    大家晚上好,,小鹿又来了..最近小鹿特别忙,忙到没时间发表博客了(注:以下内容过于简单请大家不要喷,仅提供初学者学习) 今天发表两篇文章,分别是讲解模拟QQ表情的实现,先给大家看效果图,,,, 开始了 ...

  2. Android开发之仿QQ表情实现(下)

    大家中午好,,,,,,小鹿吃草刚回来真是不好意思,,,, 上篇文章已经讲到GirdView的使用,本节内容是基于上篇内容实现更完美的QQ表情的实现,具体的说,本节内容实现的QQ表情是使用了GirdVi ...

  3. iOS 【快速集成QQ表情键盘】

    Demo演示: 如果是UITextView,导入#import "UITextView+YZEmotion.h" 如果是UITextField,导入#import "UI ...

  4. Android最完整的仿QQ表情聊天图文展示代码示例

    安卓最完整的表情聊天特效(大家可以看我上一篇文章websocket的整合,这是他的后续) 首先我们需要知道安卓输入的是EditText 显示的内容是TextView, 但是TextView里面又只能显 ...

  5. 自定义控件--仿QQ表情面板

    上个图: 1.FaceGridView.java package com.example.test;import java.io.IOException; import java.util.Array ...

  6. ios 表情符号 键盘_iOS中表情键盘的完整实现方法详解

    前言 最近在公司做了个表情键盘的需求,这个需求的技术难度不会很大,比较偏向业务.但是要把用户体验做的好也是不容易的,其中有几个点需要特别注意.话不多说,下面开始正文(注:本文对应的Demo放在Gith ...

  7. 转载 仿微信表情与软键盘冲突

    android高仿微信表情输入与键盘输入(详细实现分析) 本文是我在做仿微信IM时,解决表情栏与软键盘冲突时参考的文章,很有价值,故在此将之转载,以便后期学习. 目录(?)[+] 解决表情与键盘切换跳 ...

  8. android 表情键盘切换,Android仿微信键盘切换效果

    Android 仿微信的键盘切换(录音,表情,文字,其他),IM通讯,类似朋友圈只要涉及到文字等相关的app都会要涉及到键盘的处理,今天就给大家分享一下Android 仿微信的键盘切换. 效果图如下: ...

  9. 仿QQ聊天(5)—聊天表情的适配

    实现发送表情 第一步:先在drawable下导入需要的一些表情.然后自己再写一个txt文件,放在assets目录下. txt文件格式如下: f000.gif就是你放在drawable下表情图片的名称, ...

最新文章

  1. .netcore 如何获取系统中所有session_集群化部署,Spring Security 要如何处理 session 共享?
  2. Linux Watchdog 机制
  3. CentOS-64位安装mysql5.7
  4. Ubuntu环境搭建系列—JavaEE篇
  5. 用jquery ajax做的select菜单,选中的效果
  6. Visual Studio Code / 开启自检文本编码方式的方法
  7. User Status code in SalesPipeline
  8. 机器学习中为什么需要梯度下降_梯度下降直觉 - 机器是如何学习的
  9. vue进行判断使用class_vue判断dom的class
  10. Appium——api常用函数
  11. android oat如何提取dex文件字节码,Android: 使用oatdump反编译oat文件
  12. 纯CSS实现非常好看的图片轮播演示
  13. uva 11178(几何)
  14. 【MySQL】B-Tree 索引和数据的碎片 以及 Alert Table 会触发数据整理?
  15. 计算机 大文件查找,win7笔记本电脑如何快速查找大文件
  16. 1.Head First Java --- 进入Java的世界
  17. Java 连接 Memcached 服务
  18. Parse分析之 -- Enum.Parse
  19. 用什么软件写html语言,写html代码用什么软件
  20. 最强 IOS系统改定位

热门文章

  1. Word-已经设置多级列表的情况下下,引用题注还是从“0-1”开始
  2. 匡庐奇秀,庐山云雾翠
  3. 深入理解Java虚拟机02—类加载机制
  4. 计算机电源更改,win7更改电源设置在哪?
  5. 项目独享IP,游戏工作室最佳的选择
  6. ENVI5.0 SP3下Pleiades(普莱亚)数据处理
  7. vscode中下载淘宝镜像后,输入cnpm -v指令显示安装失败,解决系统禁止运行脚本问题,并修改cnpm下载包的地址更改为淘宝镜像地址。
  8. pr里运动预览框锚点消失
  9. 如何用Python写一个模拟的英雄联盟登陆系统!!!(详解)
  10. 抖音壁纸小程序免费搭建教程