UITextView自适应高度,同时可以设置最大高度, 类似于QQ微信输入框效果,支持表情的输入
来源:互联网 发布:单片机产生时序信号 编辑:程序博客网 时间:2024/06/06 00:45
需求:
* 在textView输入的内容的时候,需要textView根据内容自适应高度;
* 同时设置最大高度, 当textView高度大于设置的最大高度的时候, 设置textView的高度为最大高度;
* textView高度小于最大高度的时候不允许让其内容滑动, 否则让其内容可以滑动
* 可以输入表情, 同时也可以将输入框的带有表情的内容转换成字符串;
自适应高度:
在UITextView的代理方法- (void)textViewDidChange:(UITextView *)textView;
中实现
- (void)textViewDidChange:(UITextView *)textView { ///> 计算文字高度 CGFloat height = ceilf([textView sizeThatFits:CGSizeMake(textView.frame.size.width, MAXFLOAT)].height); if (height >= 100) { textView.scrollEnabled = YES; ///> 当textView高度大于等于最大高度的时候让其可以滚动 height = 100; ///> 设置最大高度 } ///> 重新设置frame, textView往上增长高度 textView.frame = CGRectMake(0, CGRectGetMaxY(textView.frame) - height, self.view.bounds.size.width, height); [textView layoutIfNeeded];}
这样就可以实现textView高度的自适应了, 同时高度一直小于100
输入表情(不支持拷贝粘贴)
创建表情按钮, 这里创建了一个view, 添加了四个表情按钮, 作为键盘的辅助视图
///> 创建键盘辅助视图- (void)creatKeyBordInputAccessoryView { UIView *inputAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 40)]; inputAccessoryView.backgroundColor = [UIColor redColor]; ///> 循环创建按钮 for (int i = 0; i < 4; i ++) { UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; button.tag = 2000 + i; ///> 设置表情图片作为按钮的背景图片 [button setBackgroundImage:[self imageWithName:[NSString stringWithFormat:@"02%d@2x",i]] forState:UIControlStateNormal]; button.frame = CGRectMake(i * (inputAccessoryView.frame.size.width / 4.0) + inputAccessoryView.frame.size.width / 8.0 - 20, 0, 40, 40); [button addTarget:self action:@selector(handleButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [inputAccessoryView addSubview:button]; } self.textView.inputAccessoryView = inputAccessoryView;}///> 根据表情名字, 返回对应的表情图片- (UIImage *)imageWithName:(NSString *)name { ///> 获取表情包路径 NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"EmoticonQQ" ofType:@"bundle"]]; ///> 获取name对应的表情图片路径 NSString *imagePath = [bundle pathForResource:name ofType:@"png"]; ///> 获取name对应的表情图片 UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; return image;}
使用NSTextAttachment
在文字中插入图片, 进入系统API会发现NSTextAttachment有一个image属性, 还有一个bounds属性
image就是用来设置图片的, bounds用来设置大小及位置, 接下来就要用到属性字符串NSAttributedString
系统对它提供了一个类方法, 参数是NSTextAttachment
类型的, 不多说上代码
///> 辅助视图上按钮事件, 向textView中插入表情图片- (void)handleButtonAction:(UIButton *)sender { // YBTextAttachment是继承自NSTextAttachment的一个类, 添加了一个emojName属性 // 可以在这个类里边重写- (CGRect)attachmentBoundsForTextContainer: proposedLineFragment: glyphPosition: characterIndex: 方法可实现图片和文字大小一致 ///> 设置装载图片的控件(在这里理解成一个图片容器控件,这样好理解) YBTextAttachment *attachment = [[YBTextAttachment alloc] init]; ///> 将按钮上的图片插入到属性字符串中 attachment.image = sender.currentBackgroundImage; ///> 设置表情图片控件bounds attachment.bounds = CGRectMake(0, 0, 20, 20); ///> 设置表情文字, 在表情转换字符串的时候要用 switch (sender.tag) { case 2000: attachment.emojName = @"[/色]"; break; case 2001: attachment.emojName = @"[/害羞]"; break; case 2002: attachment.emojName = @"[/得意]"; break; case 2003: attachment.emojName = @"[/吐]"; break; default: break; } ///> 创建属性字符串, 使用装载有表情图片NSTextAttachment对象初始化创建属性字符串 NSAttributedString *attrinbutedStr = [NSAttributedString attributedStringWithAttachment:attachment]; ///> 在光标位置插入带有图片的属性字符串 [self.textView.textStorage insertAttributedString:attrinbutedStr atIndex:self.textView.selectedRange.location]; ///> 设置光标位置, 将光标向后移动 self.textView.selectedRange = NSMakeRange(self.textView.selectedRange.location + 1, self.textView.selectedRange.length); ///> 输入的时候调用textView代理方法, 更新textView以及文字内容 [self textViewDidChange:self.textView];}
这样在点击键盘辅助视图上的表情按钮的时候就可以在输入框里边显示表情了
将输入框带有表情的内容转换成字符串
对textView的textStorage进行遍历, 找到NSTextAttachment对象进行替换,然后将替换结果显示在label上
///> 按钮的点击方法, 将textView上的文字和表情以文本字符串的形式显示在label上- (void)getTextViewString:(UIButton *)sender { ///> self.textView.textStorage.string是只读的, 在这里进行拷贝一下 NSMutableString *planString = [self.textView.textStorage.string mutableCopy]; ///> 在block里边修改局部变量需要使用__block修饰 __block NSUInteger base = 0; // 遍历的是 NSTextAttachment对象, 找到以后进行替换 [self.textView.textStorage enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, self.textView.textStorage.length) options:0 usingBlock:^(YBTextAttachment *value, NSRange range, BOOL * _Nonnull stop) { ///> 注意这里的range是遍历value在原来字符串的range, 替换过后, range要相应的修改 if (value) { [planString replaceCharactersInRange:NSMakeRange(range.location + base, range.length) withString:value.emojName]; ///> 输入表情的时候设置的表情名字在这里用到, 表情的长度为1 base = base + value.emojName.length - 1; } }]; self.label.text = planString;}
将带有表情文字的字符串转换成属性字符串
这里将label上的内容转换成属性字符串, 显示在textView上, 如果有表情文字,使其显示对应的表情图片, 使用正则表达式将表情匹配出来进行替换, 废话不多说, 上代码:
- (void)getLabelTextToTextView:(UIButton *)sender { ///> 使用正则将表情文字匹配出来, 然后将其替换成表情图片 NSString *str = self.label.text; NSMutableAttributedString *attrinbutedStr = [[NSMutableAttributedString alloc] initWithString:str]; NSString *regexStr = @"\\[/\\w+\\]"; NSError *error = nil; NSRegularExpression *regExp = [[NSRegularExpression alloc] initWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:&error]; if (!error && str != nil && str.length != 0) { //> 对str的匹配结果 NSArray *resultArr = [regExp matchesInString:str options:0 range:NSMakeRange(0, str.length)]; NSUInteger base = 0; //> 遍历匹配结果进行替换 for (NSTextCheckingResult *result in resultArr) { ///> 要替换的字符串 NSString *emojStr = [str substringWithRange:result.range]; ///> 判断表情包里边是否包含该表情 BOOL isContain = [self isContainObjectWith:emojStr]; if (isContain) { ///> 如果表情包里边有该表情, 则进行替换, 如果没有不进行操作 YBTextAttachment *attachment = [YBTextAttachment new]; ///> 根据表情文字获取对应表情图片 attachment.image = [self imageWithName:self.emojDict[emojStr]]; attachment.bounds = CGRectMake(0, 0, 20, 20); ///> 设置表情对应的文字 attachment.emojName = emojStr; ///> 创建包含表情图片的属性字符串 NSAttributedString *tempAttributedStr = [NSAttributedString attributedStringWithAttachment:attachment]; ///> 将包含表情图片的属性字符串将表情文字替换掉, 这里要注意range, 表情的长度为1 [attrinbutedStr replaceCharactersInRange:NSMakeRange(result.range.location - base, result.range.length) withAttributedString:tempAttributedStr]; base = base + emojStr.length - 1; } } } self.textView.attributedText = attrinbutedStr; [self textViewDidChange:self.textView];}///> 判断字典(表情包)所有key中是否含有相同的字符串(表情文字)- (BOOL)isContainObjectWith:(NSString *)str { BOOL isContain = NO; for (NSString *obj in self.emojDict.allKeys) { if ([obj isEqualToString:str]) { isContain = YES; break; ///> 如果有则停止循环 } } return isContain;}
这样就可以实现基本的效果了, 这样会发现输入的文字大小或许不是我们想要的, 那么在UITextView代理方法- (void)textViewDidChange:(UITextView *)textView
中添加如下代码, 这里注意, 下边代码要写在计算高度之前, 不然计算textView高度会有错误;
NSRange wholeRange = NSMakeRange(0, textView.textStorage.length); [textView.textStorage removeAttribute:NSFontAttributeName range:wholeRange]; ///> 这里将字体大小设置为20, 和表情的高度一样, 这样看起来就好多了 [textView.textStorage addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20.0] range:wholeRange];
最终效果:
Demo地址 如果有不足欢迎指正, 大神略过!
- UITextView自适应高度,同时可以设置最大高度, 类似于QQ微信输入框效果,支持表情的输入
- iOS UITextView输入时自适应高度,placeholderLabel的设置。
- UITextView 评论输入框 高度自适应
- 高度自适应的输入框
- 输入框高度自适应
- 基于JQ 根据输入内容自适应输入框高度 支持输入增高 渲染时设置高度和内容一致
- 模仿QQ、微信表情输入框
- 文本输入框自适应高度
- textarea输入框自适应高度
- UITextView高度随文字自动增加类似于微信
- UITextView输入框,动态算高度
- 如何设置文本输入框的高度?
- iOS--UITextView的高度自适应
- Android: 实现类似QQ、微信的表情输入键盘
- Android: 实现类似QQ、微信的表情输入键盘
- iOS输入框根据键盘高度自适应
- 模拟新浪微博评论textarea输入框随着输入内容增多输入框高度自适应
- UITextview 根据输入的内容动态改变高度
- json的排序和筛选
- Vim使用进阶
- UPnP的介绍和理解
- Java中抽象类和接口的区别
- SqlBulkCopy(批量复制)使用方法
- UITextView自适应高度,同时可以设置最大高度, 类似于QQ微信输入框效果,支持表情的输入
- 《数字技术》连载30:第4章 信息的寄存传输和转换 第3节 代码的转换
- 数据库分布式架构巧设计
- Excel中sheet名字最大长度的坑
- Android 进阶之路:常见设计模式之观察者模式
- redis与MySQL结合
- Golang从入门到精通(十九):Golang并发编程之Channel
- android studio 安装配置svn
- 为什么选择多域名通配符SSL证书?