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 ...
随机推荐
- ASP.NET Core 2.2 基础知识(十三) WebAPI 概述
我们先创建一个 WebAPI 项目,看看官方给的模板到底有哪些东西 官方给出的模板: [Route("api/[controller]")] [ApiController] pub ...
- 初识.NET Core
dotnet new console dotnet new web dotnet new webapi dotnet run dotnet build -r win-x64 dotnet publis ...
- Integer 类和 int 的区别
http://www.cnblogs.com/ysocean/p/8075676.html public static void main(String[] args) { Integer i ...
- java中Frame Jpanel等中间显示
几种是窗口中间显示的方法: 1.Frame int windowWidth = frame.getWidth(); //获得窗口宽 int windowHeight = frame.getHeight ...
- AtCoder - 2567 RGB Sequence
Problem Statement There are N squares arranged in a row. The squares are numbered 1, 2, …, N, from l ...
- [Gym101194G][CHINA-Final2016]Pandaria
题目大意: 给你一个$n(n\le10^5)$个点,$m(m\le2\times10^5)$条边的无向图,每个点有一个颜色$c_i$,每条边有一个边权$w_i$.$q(q\le2\times10^5) ...
- 一个强大的UI node 抽象
基于cocos2d -x的一个强大的 界面对象的基类 ---@type uinode ui 对象的抽象 --@usage -- 界面打开的执行流程 -- 带*的是可选重写的函数,不带*的为必须实现的 ...
- java-继承-类变量与实例变量
父类中的类的变量(静态属性)与其子类共享一份. 父类中的实例变量与其子类各自维护各自的.
- Cisco模拟器Web-IOU使用说明 转
http://blog.sina.com.cn/s/blog_af0abf1f0102uztk.html GNS3作为使用最多的Cisco官方模拟器,是因为它使用简单,所有设置图形化,是一款非常强 ...
- ASP.NET Core 1.0基础之日志
过年出去玩了一圈,回来继续翻译.前两天偷懒没有翻译,只是转了两篇C# 7计划中的新features,大家还是很支持的.现在继续完善这个系列. 来源https://docs.asp.net/en/lat ...