iOS即时通讯输入框随字数自适应高度
前言
本人最近在研究socket与聊天界面的UI,在写聊天界面UI的时候是模仿微信的界面其中的文字输入框会随着字数的多少而自适应高度,当然超过某个行数输入框的高度就不会增加了变为可滚动,
具体效果
运行效果图

实现过程
我的思路是用约束来实现,输入区域用UITextView来实现;约束可以使用AutoLayout或者是第三方库Masonry来实现,但是他们的实现原理是一样的。为了方便我使用了Xib加AutoLayout来实现的,我是根据UITextView的字数,宽度固定来计算出文字的高度,从而实现UITextView的高度自适应。
我们都知道一般的聊天软件的界面(微信为例)输入框左边是一个按钮切换语音或者文字,输入框右边是表情符号和切换出发送照片等功能;当然本文主要是介绍输入框TextView的自适应,原谅我把其他东西省略了。首先textView需要一个BackVew,我们拖进去一个UIview,让它相对于父视图居左居右为0,居底部也为0,另外还需要给它一个初始高度,一般情况下是textView是一行文字的高度+textView距离它的顶部距离和底部距离。比如,我让textView距离它的backView底部与顶部分别是5,textView的字号是系统17号字,那么textView是一行的时候它的高度就是37,而这时候backView的初始高度就是37+5+5=47。textView居底部与顶部分别是5,距离左右的具体可以根据你们设计给的UI而定。这里的关键是当textView的字数变化时,我们通过计算得到当前字数应该显示的高度,我们得到这个值后适当的调增backView的高度,因为backView是相对于底部约束,增加高度后就会向上增加,而textView是依据backView的顶部与底部来约束的所以就会跟随者backView的高度变化而变化。从而实现textView自适应高度。
完后上面的约束之后,我们需要把backView、textView、backView的高度约束以及backView距离底部的约束都拉到代码中成为属性。

在viewdidload方法里面实现textView的一些设置
self.textView.delegate = self;
self.textView.scrollEnabled = NO;
self.textView.scrollsToTop = NO;
self.textView.layer.borderWidth = 1;
self.textView.layer.cornerRadius = 5;
self.textView.font = [UIFont systemFontOfSize:17];
//当textview的字符串为0时发送(rerurn)键无效
self.textView.enablesReturnKeyAutomatically = YES;
self.textView.keyboardType = UIKeyboardTypeDefault;
//键盘return样式变成发送
self.textView.returnKeyType = UIReturnKeySend;
当键盘升起的时候我们需要调整backView具体底部的距离,防止键盘升起遮挡textView,所以要实现监听键盘高度
//监听键盘
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardWillChangeFrameNotification object:nil];
实现当键盘升起或者落下的方法
- (void)keyboardWasShown:(NSNotification*)aNotification {
// 获取键盘弹出时长
CGFloat duration = [aNotification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
//键盘高度
CGRect keyBoardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat screenH = [UIScreen mainScreen].bounds.size.height;
//调增backView距离父视图底部的距离
_backViewBottomHCons.constant = keyBoardFrame.origin.y != screenH?keyBoardFrame.size.height:0;
[UIView animateWithDuration:duration animations:^{
[self.view layoutIfNeeded];
}];
}
设置textView的最大高度,这个与你设置的最大行数有关
// 计算最大高度 = (每行高度 * 总行数 + 文字上下间距)
_maxTextH = ceil(self.textView.font.lineHeight * 4 + self.textView.textContainerInset.top + self.textView.textContainerInset.bottom);
实现textView的代理方法,下面的代码方法是当textView的text发生改变时会调用,我们可以计算文字的高度,调整backView的高度。
- (void)textViewDidChange:(UITextView *)textView {
NSInteger height = ceilf([self.textView sizeThatFits:CGSizeMake(self.textView.bounds.size.width, MAXFLOAT)].height);
if (_textOldH!=height) {
// 最大高度,可以滚动
self.textView.scrollEnabled = height > _maxTextH && _maxTextH > 0;
if (self.textView.scrollEnabled==NO) {
_backViewHCons.constant = height + 10;//距离上下边框各为5,所以加10
[self.view layoutIfNeeded];
}
_textOldH = height;
}
}
我们上面讲键盘的return键设置了样式是send,所以当用户再点击return键时不应该是换行而是实现send的业务逻辑,所以需要实现下面的代理。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if (textView==self.textView && [text isEqualToString:@"\n"]){ //判断输入的字是否是回车,即按下return
//在这里做你响应return键的代码
textView.text = nil;
[self textViewDidChange:textView];
return NO; //这里返回NO,就代表return键值失效,即页面上按下return,不会出现换行,如果为yes,则输入页面会换行
}
return YES;
}
总结一下,这里的关键是当textView的字数变化时,我们通过计算得到当前字数应该显示的高度,我们得到这个值后适当的调增backView的高度,因为backView是相对于底部约束,增加高度后就会向上增加,而textView是依据backView的顶部与底部来约束的所以就会跟随者backView的高度变化而变化。从而实现textView自适应高度。
补充
暂时没有
iOS即时通讯输入框随字数自适应高度
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
iOS即时通讯输入框随字数自适应高度的更多相关文章
- iOS 即时通讯,从入门到 “放弃”?
原文链接:http://www.jianshu.com/p/2dbb360886a8 本文会用实例的方式,将 iOS 各种 IM 的方案都简单的实现一遍.并且提供一些选型.实现细节以及优化的建议. — ...
- iOS即时通讯之CocoaAsyncSocket源码解析三
原文 前言 本文实例Github地址:即时通讯的数据粘包.断包处理实例. 本文旨以实例的方式,使用CocoaAsyncSocket这个框架进行数据封包和拆包.来解决频繁的数据发送下,导致的数据粘包.以 ...
- iOS即时通讯之CocoaAsyncSocket源码解析五
接上篇:iOS即时通讯之CocoaAsyncSocket源码解析四 原文 前言: 本文为CocoaAsyncSocket Read篇终,将重点涉及该框架是如何利用缓冲区对数据进行读取. ...
- iOS即时通讯之CocoaAsyncSocket源码解析四
原文 前言: 本文为CocoaAsyncSocket源码系列中第二篇:Read篇,将重点涉及该框架是如何利用缓冲区对数据进行读取.以及各种情况下的数据包处理,其中还包括普通的.和基于TLS的不同读取操 ...
- iOS即时通讯之CocoaAsyncSocket源码解析二
原文 前言 本文承接上文:iOS即时通讯之CocoaAsyncSocket源码解析一 上文我们提到了GCDAsyncSocket的初始化,以及最终connect之前的准备工作,包括一些错误检查:本机地 ...
- iOS即时通讯之CocoaAsyncSocket源码解析一
申明:本文内容属于转载整理,原文连接 前言: CocoaAsyncSocket是谷歌的开发者,基于BSD-Socket写的一个IM框架,它给Mac和iOS提供了易于使用的.强大的异步套接字库,向上封装 ...
- iOS 即时通讯 + 仿微信聊天框架 + 源码
这些你造吗? 即时通讯(IM),在IOS这片江湖里面已经算是一个老者了,我这小旋风也是在很早以前巡山的时候,就知道有即时通讯这个妖怪,以前也多多少少接触过一些,在造APP的时候用过,哎呀,说着说着就感 ...
- iOS:即时通讯之<了解篇 SocKet>
什么是socket? 计算机专业术语就是: 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.Socket的英文原义是“孔”或“插座”.作为BSD UNIX的进 ...
- iOS 设置UILabel的行间距并自适应高度
NSString *contentStr = @"总以为,在最初的地方,有一个最原来的我,就也会有一个最原来的你"; UILabel *tempLabel = [[UILabel ...
随机推荐
- gaggd
####算法一 暴力枚举所有可能的$a_2$并递推判断.复杂度$O(r \times k)$,预期得分10分. ####算法二 $a_k$可以表示为$a_1$与$a_2$的线性组合.使用递推计算出系数 ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1215 Solved: 484[S ...
- 【转】巧用局部变量提升javascript性能
转自:http://www.jb51.net/article/47219.htm 巧用局部变量可以有效提升javascript性能,下面有个不错的示例,大家可以参考下 javascript中一 ...
- HDU 多校1.4
Division Game Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- Android学习--跨程序共享数据之内容提供其探究
什么是内容提供器? 跨程序共享数据之内容提供器,这是个什么功能?看到这个名称的时候最能给我们提供信息的应该是“跨程序”这个词了,是的重点就是这个词,这个内容提供器的作用主要是用于在不同的引用程序之间实 ...
- POJ1300Door Man(欧拉回路)
Door Man Time Limit: 1000MS Memory Limi ...
- CentOS 安装 Zookeeper 版本任选
Zookeeper下载地址各种版本自己选择: https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/ Zookeeper 3.4.13版本下载地址 ...
- [BZOJ1095]捉迷藏
点了动态点分治的科技树,这道题是树形态不变的动态点分治,形态变化的话...待会补 考虑点分治过程中的这样一种结构:按递归层次把当前层的重心与上层重心互相连接,这就是点分治树,容易看出它的树高只有$O( ...
- 【博弈论】【SG函数】【找规律】Gym - 101147A - The game of Osho
以后这种题还是不能空想,必须打个表看看,规律还是比较好找的……具体是啥看代码.用SG函数暴力的部分就不放了. #include<cstdio> using namespace std; i ...
- [OpenJudge8782][划分DP]乘积最大
乘积最大 总时间限制: 1000ms 内存限制: 65536kB [描述] 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛, ...