iOS 自定义键盘+表情布局实现

原创 2016年08月31日 08:49:20

本节主要内容:

1.自定义键盘--将工具栏添加到键盘上,并实现切换
2.实现进入到系统相册选取图片
3.实现表情布局
4.实现系统键盘和表情视图之间的切换
5.表情消息的追加

一、*自定义键盘

创建子视图,为系统键盘添加工具栏。例子中创建了textView和一个带有5个button的编辑工具栏

#pragma mark - 创建子视图
- (void)creactSubView{

    //1 添加_textView
    _textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight-50)];
    _textView.backgroundColor = [UIColor clearColor];
    _textView.font = [UIFont systemFontOfSize:15.0];
    [_textView becomeFirstResponder];
    [self.view addSubview:_textView];

    //2 编辑栏
    _editorView = [[UIView alloc] initWithFrame:CGRectMake(0, _textView.bottom, kScreenWidth, 50)];
    _editorView.backgroundColor = [UIColor clearColor];
    //***将_editorView添加到系统键盘上,利用下面的inputAccessoryView方法
    _textView.inputAccessoryView = _editorView;
    //添加5个按钮
    NSArray *imgArr = @[
                        @"compose_toolbar_1.png",
                        @"compose_toolbar_3.png",
                        @"compose_toolbar_4.png",
                        @"compose_toolbar_5.png",
                        @"compose_toolbar_6.png"
                        ];
    CGFloat btnWidth = kScreenWidth/5;

    for (int i = 0; i<imgArr.count; i++) {
        ThemeButton *button = [[ThemeButton alloc] initWithFrame:CGRectMake(btnWidth*i, 5, btnWidth, 40)];

        button.imageName = imgArr[i];

        [button addTarget:self action:@selector(pressAction:) forControlEvents:UIControlEventTouchUpInside];
        button.tag = 1000+i;

        [_editorView addSubview:button];
    }
}

二、*进入系统相册选取图片

按钮1的响应事件—实现进入系统相册选取图片(单张)

switch (button.tag - 1000) {
        case 0:
            NSLog(@"点击第一个按钮");
        {
            //由底部弹出的弹窗
            UIAlertController *alter = [UIAlertController alertControllerWithTitle:@"选取图片" message:nil preferredStyle:UIAlertControllerStyleActionSheet];

            UIAlertAction *action = [UIAlertAction actionWithTitle:@"相册" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

                //选取相册
                UIImagePickerController *picker = [[UIImagePickerController alloc] init];

                picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
                picker.delegate = self;
                //模态视图 弹出相册
                [self presentViewController:picker animated:YES completion:nil];
            }];

            [alter addAction:action];

            [self presentViewController:alter animated:YES completion:nil];

        }
            break;

三、*表情布局

要实现的效果:

所有表情分成几页,每页按照4行7列进行排列,点击任意表情会出现该表情的放大镜,放大镜上有该表情和文字。能够实现页面的滑动。

思路:

1.数据处理

从plist文件中取出所有文件,将其存放进一个大的数组中,将这个大数组分割成28个数据一组的小数组,小数组的数量将会对应页面的数量。而在每个小数组里面,这28个数据将会按照4行7列进行排列。

2.页面处理

由外至内视图分别是:UIView->UIScrolleView->UIView->UIImageView(表情视图和选中视图)

代码:

FaceView

.h文件

#import <UIKit/UIKit.h>
#import "UIViewExt.h"

@interface FaceView : UIView
@property (nonatomic, strong) NSMutableArray *items;//表情大数组
@property (nonatomic, strong) UIImageView *selectImgView;//选中的放大镜视图
@property (nonatomic, assign) NSString *selectImgName;//选中的表情名字
@property (nonatomic, strong) UILabel *label;
@end

.m文件

#import "FaceView.h"
#import "Header.h"

#define imgSize 30
@implementation FaceView

- (instancetype) initWithFrame:(CGRect)frame {

    if ([super initWithFrame:frame]) {

        [self loadPlist];
        _label = [[UILabel alloc] initWithFrame:CGRectMake(17, 40, 50, 20)];
        _label.font = [UIFont systemFontOfSize:12.0];
    }
    return self;
}

//整理表情
- (void) loadPlist {

    //获取plist文件
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"emoticons.plist" ofType:nil];
    //所有表情数组
    NSArray *array = [NSArray arrayWithContentsOfFile:filePath];
    //大数组
   _items = [NSMutableArray array];
    //小数组
    NSMutableArray *items2D = nil;
    for (int i = 0; i < array.count; i++) {

        //创建小数组
        if (items2D == nil || items2D.count == 28) {
            items2D = [NSMutableArray array];
            [_items addObject:items2D];
        }

        NSDictionary *faceDic = [array objectAtIndex:i];
        [items2D addObject:faceDic];
    }
    //内部写死宽高
    self.width = kScreenWidth * _items.count;
    self.height = 4 * itemSize;
}

//绘制
- (void)drawRect:(CGRect)rect {
    //确定行和列
    CGFloat row = 0;
    CGFloat culom = 0;
    //拿表情
    for (int i = 0; i < _items.count; i++) {

        NSMutableArray *item2D = _items[i];

        for (int j = 0; j < item2D.count; j++) {

            NSDictionary *dic = item2D[j];
            //图片名字
            NSString *imageName = [dic objectForKey:@"png"];
            UIImage *img = [UIImage imageNamed:imageName];

            CGFloat x = culom * itemSize + (itemSize-imgSize)/2 + kScreenWidth * i;
            CGFloat y = row * itemSize + (itemSize - imgSize)/2;
            //绘制
            [img drawInRect:CGRectMake(x, y, imgSize, imgSize)];

            //更新行和列
            culom++;
            if (culom == 7) {
                culom = 0;
                row++;
            }
            if (row == 4) {
                row = 0;
            }   
        }
    }
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    //放大镜不隐藏
    _selectImgView.hidden = NO;

    //禁止滑动
    if ([self.superview isKindOfClass:[UIScrollView class]]) {
        UIScrollView *scrollV = (UIScrollView *) self.superview;
        scrollV.scrollEnabled = NO;
    }

    //拿到触摸的坐标
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];

    [self touchFace:point];


}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];

    [self touchFace:point];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    //隐藏放大镜
    _selectImgView.hidden = YES;

    //开启滑动
    if ([self.superview isKindOfClass:[UIScrollView class]]) {
        UIScrollView *scrollV = (UIScrollView *)self.superview;
        scrollV.scrollEnabled = YES;
    }

    //回调block

}

//寻找点击的表情
- (void) touchFace:(CGPoint) point {
    //1.当前页
    NSInteger page = point.x/kScreenWidth;
    //容错处理
    if (page>=_items.count || page < 0) {
        return;
    }
    //确定小数组的索引
    /**根据这个计算
     CGFloat x = culom *itemSize + (itemSize-imgSize)/2 + kScreenWidth*i;
     CGFloat y = row *itemSize +(itemSize-imgSize)/2;
     */
    NSInteger culom = (point.x - ((itemSize-imgSize)/2 + kScreenWidth*page))/itemSize;//列
    NSInteger row = (point.y - (itemSize-imgSize)/2)/itemSize;//行
    //容错处理
    if (culom >6) culom =6;
    if (culom <0) culom =0;
    if (row >3) row =3;
    if (row <0) row =0;

    //根据当前页面坐标计算行和咧
    NSInteger index = row*7+culom;
    //处理最后一页数组越界
    if (page == _items.count-1) {
        //通过页面获取小数组
        NSArray *item2D = _items[page];

        if (index>item2D.count-1) {
            return;
        }
    }
    NSArray *item2D = _items[page];
    NSDictionary *faceDic = item2D[index];
    //表情图片名
    NSString *imgName = faceDic[@"png"];
    //表情中文名
    NSString *faceName = faceDic[@"chs"];


    if (![self.selectImgName isEqualToString:faceName]) {
        //确定放大镜的位置
        CGFloat bottom = row *itemSize +itemSize/2;
        CGFloat x = culom *itemSize + itemSize/2 + page *kScreenWidth;
        self.selectImgView.center = CGPointMake(x, 0);
        self.selectImgView.bottom = bottom;

        //赋值-选中的表情图片显示
        UIImageView *imgView =[self.selectImgView viewWithTag:1100];
        imgView.image = [UIImage imageNamed:imgName];

        self.selectImgName = faceName;
         [_selectImgView addSubview:_label];

        //选中的表情名
        _label.text = _selectImgName;

    }

    //发送通知--参数:选中的图片名faceName
    NSDictionary *userInfo = @{@"imageName" : faceName};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"imageNameNo"
                                                        object:nil
                                                      userInfo:userInfo];
}

//选中视图
- (UIImageView *) selectImgView {

    if (_selectImgView == nil) {
        //创建选中视图
        _selectImgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"emoticon_keyboard_magnifier.png"]];
        [_selectImgView sizeToFit];
        [self addSubview:_selectImgView];
        //选中视图中的表情
        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake((_selectImgView.width-imgSize)/2, 15, imgSize, imgSize)];
        imgView.tag = 1100;
        [_selectImgView addSubview:imgView];
    }
    return _selectImgView;
}

@end

FaceFnel

.h文件

#import <UIKit/UIKit.h>
#import "FaceView.h"

@interface FaceFnel : UIView <UIScrollViewDelegate>

@end

.m文件

#import "FaceFnel.h"
#import "Header.h"

@implementation FaceFnel
/**
 faceView---表情视图
 scroll----滑动视图
 page---分页控件
 */
- (instancetype) initWithFrame:(CGRect)frame {

    if ([super initWithFrame:frame]) {

        [self createSubView];
    }
    return  self;
}

- (void) createSubView {

    //创建faceView
    FaceView *faceView = [[FaceView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
    faceView.backgroundColor = [UIColor clearColor];

    //创建scrollView
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, faceView.height)];
    scrollView.contentSize = CGSizeMake(faceView.width, faceView.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    //裁剪
    scrollView.clipsToBounds = NO;
    scrollView.pagingEnabled = YES;
    scrollView.delegate = self;
    [scrollView addSubview:faceView];
    [self addSubview:scrollView];

    //创建分页控件
    UIPageControl *pageC = [[UIPageControl alloc] initWithFrame:CGRectMake(0, faceView.bottom, kScreenWidth, 20)];
    pageC.numberOfPages = faceView.items.count;
    pageC.tag = 2017;

    //当前视图的宽高计算
    self.width = kScreenWidth;
    self.height = faceView.height + pageC.height;

    [self addSubview:pageC];
}

#pragma mark -滑动视图代理方法
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {

    //计算index--index代表圆点的下标
    NSInteger index = scrollView.contentOffset.x/kScreenWidth;

    UIPageControl *pageC = (UIPageControl *) [self viewWithTag:2017];

    pageC.currentPage = index;
}

- (void) drawRect:(CGRect)rect {

    UIImage *img = [UIImage imageNamed:@"emoticon_keyboard_background.png"];
    [img drawInRect:rect];
}

@end
#pragma mark - 图片的代理方法
- (void)imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(nonnull NSDictionary<NSString *,id> *)info {

    [picker dismissViewControllerAnimated:YES completion:nil];
    [_textView becomeFirstResponder];

    UIImage *img = info[@"UIImagePickerControllerOriginalImage"];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -30, 30, 30)];
    imageView.image = img;
    _sendImg = img;
    [_editorView addSubview:imageView];
}

四、系统键盘与表情视图之间相互切换

case 4:
        {
//            [self loadImage];
            //按钮取反
            button.selected = !button.selected;

            if (button.selected == YES) {
               //收起键盘
                [_textView resignFirstResponder];
                //显示表情视图
                _textView.inputView = _faceview;
                //弹出键盘
                [_textView becomeFirstResponder];
            } else {

                [_textView resignFirstResponder];
                //显示系统键盘
                _textView.inputView = nil;
                [_textView becomeFirstResponder];
            }
        }
            break;

五、消息追加

这里的思路是将图片的中文名作为参数,利用通知传过来,将其复制给_textView.text上。
//发送通知
 NSDictionary *userInfo = @{@"imageName" : faceName};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"imageNameNo" object:nil userInfo:userInfo];
//接收通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ImgaeNameChange:) name:@"imageNameNo" object:nil];
#pragma mark - 通知的实现
- (void) ImgaeNameChange:(NSNotification *) noti {

    NSString *text = [noti.userInfo objectForKey:@"imageName"];
    //追加
    _textView.text = [_textView.text stringByAppendingString:text];
}
//移除通知
- (void) dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageNameNo" object:nil];
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31151129/article/details/52381526

iOS开发-------自定义简单的表情键盘(UICollectionView 集合视图)

最近制作自制表情键盘的时候,突然了解到还有一个叫做UICollectionView (集合视图)的类,就研究了一下,确实在做表情键盘上要比用 UIScrollView(滚动视图) 要简单的多,用法与 ...
  • RunIntoLove
  • RunIntoLove
  • 2015-10-04 15:24:53
  • 3248

iOS自定义表情键盘

  • 2016年12月13日 09:52
  • 217KB
  • 下载

iOS中如何自定制键盘呢?

很简陋的demo,主要是实现了自定制键盘的具体思路,里边具体“按键”要自己实现。下面只实现了对textField的键盘监控,textView的键盘是一样的。先看看效果吧: 设计模式:单例#import...
  • rolandMan_
  • rolandMan_
  • 2016-12-14 16:46:52
  • 488

Expression on the keyboard

  • 2015年08月04日 13:57
  • 1.23MB
  • 下载

iOS自定义的表情键盘

iOS自定义的表情键盘 一、关于emoji表情         随着iOS系统版本的升级,对原生emoji表情的支持也越来越丰富。emoji表情是unicode码中为表情符号设计的一组编码,当...
  • dong_vip
  • dong_vip
  • 2015-11-17 14:17:22
  • 1757

Android自定义表情键盘与输入法键盘冲突

下面输入框在界面的中间位置,点击输入框弹出输入法键盘,如果此时表情键盘打开要收回表情键盘;点击笑脸图标弹出表情键盘,如果此时输入法键盘打开则要收回输入法键盘; 由于点击输入框输入法键盘是自动弹...
  • enjoyinwind
  • enjoyinwind
  • 2015-07-28 19:27:24
  • 2937

Android 自定义键盘(完全定制,向上顶布局,点击按钮进行隐藏)

  • 2015年09月18日 12:07
  • 1.58MB
  • 下载

iOS 自定义输入键盘

输入框,键盘上滑效果
  • lovechris00
  • lovechris00
  • 2016-11-02 16:41:49
  • 764

iOS中QQ聊天界面发送消息及表情键盘的实现

该程序主要实现iOS中qq发送信息和qq表情键盘功能的实现
  • u010067452
  • u010067452
  • 2016-01-03 00:48:05
  • 2962

Android 自定义键盘 随机键盘(完全定制,向上顶布局,点击按钮进行隐藏)

之前上传的另外一个自定义键盘,并没有实现键盘弹出的时候,布局向上自动调整。(网络上所有的自定义键盘都没有添加自适应的功能,而且布局没这么好看,上一个例子资源链接为:http://download.cs...
  • omayyouhappy
  • omayyouhappy
  • 2015-09-18 15:49:14
  • 7367
收藏助手
不良信息举报
您举报文章:iOS 自定义键盘+表情布局实现
举报原因:
原因补充:

(最多只允许输入30个字)