1、需求
这里介绍一个实用小技巧,在开发过程中,有一个简单的需求:在文本输入框中进行文字和表情的同时输入,要求自己创建一个表情输入的“小键盘”。
第一时间可能想到的方法是:自己定义图片,然后添加进textField 或者Label里,进行图文混排,这样做需要费很大的功夫处理,特别痛苦。
2、解决原理
实际上,我们有很简单的方法,iOS系统自己就带有表情“键盘”,系统可以将指定的字符通过uicode编码处理,生成字符串,然后在view,textfield,textView中展示,这时系统会直接展示成图片表情的形式,其实质依然是UTF8的符号。
3、实现方法及效果
想要获取系统的表情,要首先知道表情对应的UTF8的编码方式(可以百度一下),然后将指定范围的数字转为对应的表情编码,接着将表情编码转换成字符串,并且把这些字符串放到表情数组中, 最后创建多个UIButton,用表情数组中的字符串给button的titl赋值即可。另外,iOS7之后又增加了300多个表情符号。
效果:
4、封装细节和使用
(1)通过封装的对象方法,直接实例化控件(是个UIView),设置fram,添加到视图。
(2)控件中的button是自动排列的,表情按钮和输入框的左右边界和上下边界可以根据输入的输入框大小自动计算。
(3)表情的大小在25正好
(4)本例中的编码提供最多70多个表情
5、源码的封装
(1).h文件,提供了两个方法,针对textView和textField的
@interface ZQFaceView : UIView
/**
* 生成表情输入框,会自动根据输入的范围大小进行布局
*
* @param textView 输入到的文本框
* @param frame 表情框的大小
* @param iconWH 每个表情按钮的大小,一般为25~30
*
* @return
*/
-(instancetype)initWithUItextView:(UITextView *)textView Frame:(CGRect)frame IconWH:(NSInteger)iconWH;
/**
* 生成表情输入框,会自动根据输入的范围大小进行布局
*
* @param textField 输入到textField
* @param frame 表情框的大小
* @param iconWH 每个表情按钮的大小,一般为25~30
*
* @return
*/
-(instancetype)initWithUItextField:(UITextField *)textField Frame:(CGRect)frame IconWH:(NSInteger)iconWH;
@end
(2).m文件
@interface ZQFaceView()
@property(nonatomic,strong) NSArray * faceArray;
@property(nonatomic,strong) UITextView * textView;
@property(nonatomic,strong) UITextField * textField;
@end
@implementation ZQFaceView
-(instancetype)initWithUItextView:(UITextView *)textView Frame:(CGRect)frame IconWH:(NSInteger)iconWH
{
self= [[ZQFaceView alloc]initWithFrame:frame];
self.textView=textView;
[self makeFaceKeyboard:frame IconWH:iconWH];
return self;
}
-(instancetype)initWithUItextField:(UITextField *)textField Frame:(CGRect)frame IconWH:(NSInteger)iconWH
{
self= [[ZQFaceView alloc]initWithFrame:frame];
self.textField=textField;
[self makeFaceKeyboard:frame IconWH:iconWH];
return self;
}
//构造表情键盘
-(void)makeFaceKeyboard:(CGRect)frame IconWH:(NSInteger)iconWH
{
//获取数组
NSArray * arr = [self faceArray];
//背景视图的宽高
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
//按钮之间的间距
CGFloat margin =5;
//左右边距,先给一个参考值
CGFloat marginXY =10 ;
//计算可以显示多少个按钮(每行)
NSInteger cloCount= (width +margin - 2*marginXY)/(margin+iconWH);
//再计算具体的左右边距
marginXY = (width-cloCount*iconWH-(cloCount-1)*margin)/2;
//计算几行,先给估算值
//上边距估算
CGFloat marginTop =10;
//计算几行
NSInteger totlCount =(height+margin-marginTop*2)/(iconWH+margin);
//计算头尾具体行间距
marginTop = (height - totlCount * iconWH - (totlCount-1)*margin)/2;
//计算一共有几个按钮
NSInteger num = cloCount * totlCount;
//按钮的x、y值
CGFloat x;
CGFloat y;
for (int i = 0; i < num; i++) {
UIButton * button = [[UIButton alloc]init];
x= marginXY + i%cloCount*(iconWH+margin);
y= marginTop + i/cloCount*(iconWH+margin);
button.frame=CGRectMake(x, y,iconWH, iconWH);
[self addSubview:button];
button.tag=i;
[button addTarget:self action:@selector(faceClick:) forControlEvents:UIControlEventTouchUpInside];
NSString *Str = arr[i];
[button setTitle:Str forState:UIControlStateNormal];
}
}
//点击每个按钮,将表情添加到控件中
-(void)faceClick:(UIButton *)face
{
NSArray *emoji = [self faceArray];
NSString *str = emoji[face.tag];
NSLog(@"str = %@",str);
//取出原本文本框内容,和新输入的内容进行拼接
NSString * oldStr = self.textView.text;
NSString * newStr = [oldStr stringByAppendingString:str];
//根据输入目标进行赋值
if(self.textView)
{
self.textView.text=newStr;
}
if (self.textField) {
self.textField.text=newStr;
}
}
//将指定范围的数字转为对应的表情编码
-(int)EMOJI_CODE_TO_SYMBOL:(int)x
{
return ((((0x808080F0 | (x & 0x3F000) >> 4) | (x & 0xFC0) << 10) | (x & 0x1C0000) << 18) | (x & 0x3F) << 24);
}
//获取默认表情数组,将表情编码转换成字符串
- (NSArray *)faceArray {
NSMutableArray *array = [NSMutableArray new];
for (int i=0x1F600; i<=0x1F64F; i++) {
if (i < 0x1F641 || i > 0x1F644) {
int sym = [self EMOJI_CODE_TO_SYMBOL:i];
NSString *emoT = [[NSString alloc] initWithBytes:&sym length:sizeof(sym) encoding:NSUTF8StringEncoding];
[array addObject:emoT];
}
}
return array;
}
@end
6、补充
改变表情按钮有一个简单方法,就是改变按钮的titleLabel的字体大小。