• iOS_仿QQ表情键盘


    当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

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

  • 相关阅读:
    配置iis支持.json格式的文件
    This function has none of Deterministic,no sql,or reads sql data in its declaration and binary logging is enabled(you *might* want to use the less safe log_bin_trust_function_creators variable
    IIS Asp.Net 访问 Com组件 报拒绝访问
    记一次 mysql 启动没反应
    linux 下安装 redis
    Jexus 安装asp.net mvc EF 项目引发的错误总
    在CentOS中安装arial字体
    Navigator 对象
    location 对象属性
    history对象
  • 原文地址:https://www.cnblogs.com/xiaoqiuge/p/4858057.html
Copyright © 2020-2023  润新知