一.前言

平常我们使用的表情包大多是emoji表情,而到了微信和qq上我们会见到更多更丰富的表情,那么这些表情是如何做的呢,下面就让我来带你们来揭晓答案。

注: 方法都来自互联网, 在此鸣谢走在前面铺路的前辈们.

二.准备阶段

准备一个表情包 就是一组表情如图1所示.

图1

我这里借用了一下腾讯的表情包 一共是50个表情

三.编写阶段, 这里只说明核心功能, UI简略说明.

1.效果图(you say a jb without a picture) 如图2所示.

图2

2.先画一个表情键盘

从效果图上可以看出来 下面的就是表情键盘(非常简陋! 我想吐) 咳咳... 如图3所示.

图3

这个表情键盘我是用collectionView画的(这个过程略), 使用过这个控件的人都知道, 我们还需要一个数据源来表示那些小表情, 接下来就是创建数据源的过程:

- (NSMutableArray *)faceArray {

if (!_faceArray) {

_faceArray = [NSMutableArray array];

//创建一个标签数组

NSArray *tagArr = @[@"[龇牙]", @"[吐舌]", @"[流汗]", @"[偷笑]", @"[再见]", @"[砸]", @"[擦汗]", @"[猪头]", @"[玫瑰]", @"[流泪]", @"[大哭]", @"[嘘]", @"[酷]", @"[抓狂]", @"[委屈]", @"[便便]", @"[地雷]", @"[菜刀]", @"[可爱]", @"[心心眼]", @"[害羞]", @"[帅气]", @"[吐]", @"[笑脸]", @"[生气]", @"[尴尬]", @"[惊吓]", @"[尴尬2]", @"[心]", @"[嘴唇]", @"[白眼]", @"[傲慢]", @"[难过]", @"[惊讶]", @"[疑问]", @"[睡觉]", @"[亲亲]", @"[憨笑]", @"[企鹅爱]", @"[衰]", @"[撇嘴]", @"[阴险]", @"[加油]", @"[发呆]", @"[睡着]", @"[抱抱]", @"[坏笑]", @"[飞吻]", @"[鄙视]", @"[晕]"];

for (NSInteger i = 1; i < 51; i++) {

//创建一个表情对象

FaceAttachment *model = [[FaceAttachment alloc] init];

//从第一张图片依次赋值

model.imageName = [NSString stringWithFormat:@"%03ld", i];

//刻上标签名 用途:上传服务器替换

model.tagName = tagArr[i - 1];

//将model装入数组

[_faceArray addObject:model];

}

}

return _faceArray;

}

下面是FaceAttachment

.h

#import

@interface FaceAttachment : NSTextAttachment

@property(nonatomic, strong) NSString *imageName; /** 表情图片名 */

@property(nonatomic, strong) NSString *tagName; /** 标签名 */

@property(nonatomic, assign) NSRange range; /** 位置 */

@end

.m

#import "FaceAttachment.h"

@implementation FaceAttachment

- (UIImage *)image {

return [UIImage imageNamed:_imageName];

}

@end

FaceAttachment的对象就是每个小表情, 这个model中有三个属性

imageName 图片名 其实我们看到的表情就是一个个的小图片

tagName 标签名 上传服务器时要将这些富文本中的表情 替换成普通的字符串标签才能上传

range 记录表情的位置

3.控制键盘弹出逻辑

到这里有人会提出一个问题, 切换表情键盘后怎么让光标存在?

这个问题其实很简单, 只需要把表情键盘设置为textView.inputView就行了, 使用过程是先设置好inputView再弹出键盘, 不然inputView是不会自动切换的, 如果在键盘弹出状态下切换inputView也很简单, 方法就是先回收键盘 -> 切换inputView -> 再弹出即可 下面是表情与键盘的切换代码

- (IBAction)faceButton:(id)sender {

if (!_keyBoardFlag) {

[self.view endEditing:YES];

self.textView.inputView = self.faceBoard;

[self.textView becomeFirstResponder];

[self.faceButton setImage:[UIImage imageNamed:@"键盘"] forState:UIControlStateNormal];

}

else {

[self.view endEditing:YES];

self.textView.inputView = nil;

[self.textView becomeFirstResponder];

[self.faceButton setImage:[UIImage imageNamed:@"表情"] forState:UIControlStateNormal];

}

_keyBoardFlag = !_keyBoardFlag;

}

4.插入表情的核心代码

其实原理很简单就是利用富文本进行一个表情的拼接 代码如下

+ (void)insertFaceToString:(FaceAttachment *)model textView:(UITextView *)textView {

//创建一个附件

FaceAttachment *faceAttachement = [[FaceAttachment alloc]init];

//添加表情

faceAttachement.imageName = model.imageName;

//添加标签名

faceAttachement.tagName = model.tagName;

//设置表情大小

faceAttachement.bounds = CGRectMake(0, 0, 18, 18);

//记录光标位置

NSInteger location = textView.selectedRange.location;

//插入表情

[textView.textStorage insertAttributedString:[NSAttributedString attributedStringWithAttachment:faceAttachement] atIndex:textView.selectedRange.location];

//将光标位置向前移动一个单位

textView.selectedRange = NSMakeRange(location + 1, 0);

}

其中 FaceAttachment 是继承于 NSTextAttachment 这个东西就相当于一个相框 用它装表情图片 然后拼接到文本上去, 为什么要继承 NSTextAttachment ? 因为我们要存放的东西在它原有基础上是不够的, 所以要继承 写上去三个属性

FaceAttachment的对象就是每个小表情, 这个model中有三个属性

imageName 图片名 其实我们看到的表情就是一个个的小图片

tagName 标签名 上传服务器时要将这些富文本中的表情 替换成普通的字符串标签才能上传

range 记录表情的位置

5.上传服务器

通过上面的步骤 我想你们应该对表情是如何写在文本上有一个了解了 但是我要说的是 这样的表情是不能上传到服务器的, 所以我们要把它们转化成普通的纯文本字符才能去上传 下面的代码就是把这些富文本表情转化成纯文本字符.

转化前效果图:

图4

转化后文字:

请输入文字[龇牙][龇牙][龇牙]

下面是转化代码:

- (NSString *)toString {

NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc]initWithAttributedString:self];

__block NSUInteger index = 0;

[self enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, self.length) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) {

//从富文本中遍历出 FaceAttachment 对象

if (value && [value isKindOfClass:[FaceAttachment class]]) {

FaceAttachment *faceAttachment = value;

//替换对象为[表情]

[attributeString replaceCharactersInRange:NSMakeRange(range.location + index, range.length) withString:faceAttachment.tagName];

//替换后对位置作一下调整(因为替换前长度为1替换后有可能是4 [龇牙] 也有可能是3 [晕])

index += faceAttachment.tagName.length - 1;

}

}];

return attributeString.string;

}

上面的代码自己写写 很简单的.

6.服务器上获取的纯文本转化为带表情的富文本

通过上面的步骤 我们已经可以把表情和文字都转化成纯文本的形式上传的服务器上了, 接下来我们要做的就是把服务器上获取的这些字符串再转换回表情 其实中心思想就是用正则表达式过滤出"[表情]"这样的标签并记录他们的位置, 然后创建出 FaceAttachment 对象 对 "[表情]" 这样的标签来进行替换

- (NSAttributedString *)faceWithServerString:(NSString *)string {

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]initWithString:string];

NSString *pattern = @"\\[[^\\[|^\\]]+\\]";

NSError *error = nil;

NSRegularExpression *regularExpression = [[NSRegularExpression alloc] initWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];

if (!regularExpression) {

NSLog(@"错误信息 : %@", error);

}

//将匹配到的字符存入数组

NSArray *resultArr = [regularExpression matchesInString:string options:0 range:NSMakeRange(0, string.length)];

NSMutableArray *faceModelArr = [NSMutableArray array];

for (NSTextCheckingResult *result in resultArr) {

NSRange range = result.range;

NSString *subString = [string substringWithRange:range];

for (FaceAttachment *model in self.faceArray) {

if ([subString isEqualToString:model.tagName]) {

FaceAttachment *faceAttachment = [[FaceAttachment alloc]init];

faceAttachment.imageName = model.imageName;

faceAttachment.tagName = model.tagName;

faceAttachment.range = range;

faceAttachment.bounds = CGRectMake(0, 0, 18, 18);

[faceModelArr addObject:faceAttachment];

}

}

}

faceModelArr = [NSMutableArray arrayWithArray:[[faceModelArr reverseObjectEnumerator] allObjects]];

for (FaceAttachment *faceAttachment in faceModelArr) {

NSAttributedString *faceAttributedString = [NSAttributedString attributedStringWithAttachment:faceAttachment];

[attributedString replaceCharactersInRange:faceAttachment.range withAttributedString:faceAttributedString];

}

[attributedString addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} range:NSMakeRange(0, attributedString.length)];

return attributedString;

}

四.Demo

php ios表情包,[iOS] 自定义表情包相关推荐

  1. IM界面高仿微信,android表情转ios表情,支持自定义表情,支持语音(实战界面)

    前言: 2018年底由子公司来到现在的集团公司,从互联网公司变成了企业公司.在最近一个项目里,做的辛辛苦苦,功能又被砍了.没有理由,心力交瘁!本来是打算自己做IM的,现在被砍了.我就把本地功能贡献出来 ...

  2. Android键盘自定义表情包,关于自定义表情键盘...

    在做输入的时候,除了可以输入系统的表情符号,项目中通常还要求输入表情图片 表情图片 1.正则表达式 一个正则表达式,就是一串有特定意义的字符,首先要编译成为一个Pattern对象,然后使用matche ...

  3. flutter聊天界面-自定义表情键盘实现

    flutter聊天界面-自定义表情键盘实现 flutter 是 Google推出并开源的移动应用开发框架,主打跨平台.高保真.高性能.开发者可以通过 Dart语言开发 App,一套代码同时运行在 iO ...

  4. Go 学习笔记(3)— 包概念、包特点、包名约束、main 包、包的声明、包的引用、包初始化

    1. 包的概念 Go 语言是使用包来组织源代码的,并实现命名空间的管理.任何源代码文件必须属于某个包.源码文件的第一行有效代码必须是 package pacakgeName 语句,通过该语句声明自己所 ...

  5. 关于友盟IM自定义表情包的使用

    介绍 友盟的IM是支持自定义表情的,在友盟IM自定义表情包里面,是有一个淘公仔的表情包,为了我们可以自己添加自己的的表情包,我们先看一下友盟提供的淘公仔表情包的相关文件配置. 首先我们先看一下自定义表 ...

  6. AM8 自定义表情包的实现方法

    AM8 自定义表情包的实现方法 效果描述 AM8 安装后,在\Activesoft\AMm8\emotions 目录内存储的是默认的表情符号.但有的时候我们需要增加一些新的表情符号,AM8 系统支持自 ...

  7. iOS自定义表情的实现

    现在很多App都有自己的自定义的表情,客户端可能要实现自己定表情的选择.发送和显示,这里我介绍一种简单的自定义表情的实现思路和代码. 以下介绍基本可以实现聊天中对自定义表情的需求,可结合下图来理解: ...

  8. Qt 实现聊天软件中自定义表情包(随笔记录)

    简述: QT实现自定义表情包,通过对(能够设置表情的行列数 , 表情的大小,表情的个数.最大行数等) 效果: 代码如下: EmoticonsWidget主要实现表情包窗口. EmoticonsWidg ...

  9. android 自定义表情包,android基于环信的聊天和表情自定义

    环信sdk的导入 自定义聊天界面 此处只有静态图,请谅解. 自定义表情发送 自定义聊天界面 简单说下自定义的聊天界面,一个带有recyclerview和的xml文件,和对应的adapter即可.rec ...

  10. Wireshark抓包iOS入门教程

    本文来自简书,原文地址:http://www.jianshu.com/p/c67baf5fce6d 网络抓包是个基础技能,对于网络协议的掌握有一定的要求.iOS上实现网络抓包可以用Charles(针对 ...

最新文章

  1. Apache Hudi的写时复制和读时合并
  2. UA PHYS515A 电磁理论V 电磁波与辐射11 简单辐射问题 电偶极子的辐射
  3. CEF:给客户端内嵌一个Chrome吧
  4. Android使用SAX解析XML(6)
  5. java 通配符 类_关于类:具有多个类的Java泛型通配符
  6. 荣耀手表2鸿蒙,鸿蒙2.0曝光 计划在明年用于手表手环上
  7. 如何正确选择仓储物流供应商?
  8. java office文件加水印_永中Office与统一操作系统UOS完成适配,开辟高效智能办公新领域...
  9. Error:express-session deprecated undefined resave option; provide resave option app.js:17:10
  10. sql raiserror_SQL Server PRINT和SQL Server RAISERROR语句
  11. 微信小程序 图片处理:压缩、上传、审核
  12. HTML关闭网页弹出窗口代码
  13. linux下安装MP4Box
  14. 百度地图开放平台web api 获取某项目方圆一公里的poi信息
  15. maxima学习笔记(一)
  16. 智安网络丨居安思危·洞见未来 — — 智安网络安全周报
  17. Jetson Nano资料合集
  18. 20220905 buffer overflow detected
  19. 卸载oracle apex,oracle关闭apex的jobs
  20. 单片机中时延函数易常范的错误

热门文章

  1. 家庭作业(贪心 + 并查集)
  2. R语言学习-问题解决-Error in output$nodeID : $ operator is invalid for atomic vectors
  3. 洛谷P3369 AVL树
  4. wifi良好,手机可以连接网络,电脑连接不上网络,解决方法
  5. JAVA怎么开发一个胖客户端_胖客户端瘦客户端哑终端
  6. Oracle10g或Oracle11g完全卸载正确步骤(亲身体验-详细图文教程)
  7. 操作rabbitMQ时,误删guest账户,无法登录
  8. 常见服务器默认管理口地址
  9. TopCoder SRM 688
  10. 核密度估计_拔剑-浆糊的传说_新浪博客