iOS UITextView 输入内容实时更新cell的高度
iOS UITextView 输入内容实时更新cell的高度
这篇文章介绍了在一个动态数据的 table view 中,cell 根据 text view 内容的输入实时改变 cell 和 table view 的高度。自动计算 cell 高度的功能使用 iOS 8 才支持的自适应 cell,如果你还不知道 iOS 8 自适应 cell,可以参看这篇文章:iOS 8 自适应 Cell
先上图,我们最终要实现的效果是这样的:

图 1:实时更新 cell 高度
实现上面效果的基本原理是:
在 cell 中设置好 text view 的 autolayout,让 cell 可以根据内容自适应大小
text view 中输入内容,根据内容更新 textView 的高度
调用 tableView 的 beginUpdates 和 endUpdates,重新计算 cell 的高度
将 text view 更新后的数据保存,以免 table view 滚动超过一屏再滚回来 text view 中的数据又不刷新成原来的数据了。
功能具体实现方法
新建一个项目,拉出 TableViewController,在 cell 上添加一个 UITextView。
首先设置 text view 的 autolayout,比较关键的 constraint 是要设置 textView 的高度大于等于一个值。如图:

图 2: Text view 的 autolayout 设置
然后,设置 UITextView 的 scrollEnable 为 NO。这一点很关键,如果不设置为 NO,UITextView 在内容超出 frame 后,重新设置 text view 的高度会失效,并出现滚动条。

图 3:去掉 scrolling enable 勾选
根据刚才在 storyboard 中创建的 cell,新建一个 UITableViewCell 类。
|
1
2
3
4
|
#import <uikit uikit.h="">@interface TextViewCell : UITableViewCell@property (weak, nonatomic) IBOutlet UITextView *textView;@end</uikit> |
创建 TableViewController 并初始化一些数据
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#import "TableViewController.h"#import "TextViewCell.h"@interface TableViewController ()@property (nonatomic, strong) NSArray *data;@end@implementation TableViewController- (void)viewDidLoad { [super viewDidLoad]; // 支持自适应 cell self.tableView.estimatedRowHeight = 100; self.tableView.rowHeight = UITableViewAutomaticDimension; self.data = @[@"Cell 1 ", @"Cell 2", @"Cell 3", @"Cell 4", @"Cell 5", @"Cell 6", @"Cell 7", @"Cell 8"];}#pragma mark - Table view data source- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.data count];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { TextViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TextViewCell" forIndexPath:indexPath]; cell.textView.text = self.data[indexPath.row]; return cell;} |
使用上面的代码项目已经可以运行了,但是 text view 还不能自动更新大小,下面来实现 text view 根据内容计算高度。
先在 storyboard 中,将 UITextView 的 delegate 设置为 cell

图 4:设置 UITextView 的 delegate 为 cell
在 TextViewCell.m 中实现 - (void)textViewDidChange:(UITextView *)textView,每次 text view 内容改变的时候,就重新计算一次 text view 的大小,并让 table view 更新高度。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#import "TextViewCell.h"@implementation TextViewCell- (void)textViewDidChange:(UITextView *)textView{ CGRect bounds = textView.bounds; // 计算 text view 的高度 CGSize maxSize = CGSizeMake(bounds.size.width, CGFLOAT_MAX); CGSize newSize = [textView sizeThatFits:maxSize]; bounds.size = newSize; textView.bounds = bounds; // 让 table view 重新计算高度 UITableView *tableView = [self tableView]; [tableView beginUpdates]; [tableView endUpdates];}- (UITableView *)tableView{ UIView *tableView = self.superview; while (![tableView isKindOfClass:[UITableView class]] && tableView) { tableView = tableView.superview; } return (UITableView *)tableView;}@end |
这样就已经实现了 text view 改变内容自动更新 cell 高度的功能,这篇文章没有涉及到计算 cell 高度的代码,因为计算 cell 高度的工作全部交给 iOS 8 的 autolayout 自动计算了,这让我们少写了许多令人痛苦的代码。
最后:为了防止 table view 过长,导致滚动后重新加载 cell,会让 text view 中的内容还原的问题,我们应该在更新了 text view 的内容之后保存数据。(如果是在编辑状态下,还需要考虑取消编辑后的回滚功能。 普通数组数据,可以保存一个原始数据的副本,如果用户取消编辑,就设置 data 为原始数据的副本。如果是 NSManagedObject 对象可以使用 NSUndoManage,不过这些已经超出本篇文章的内容范围了。)
为了在 text view 更新后能让 TableViewController 中的 data 更新,需要为 cell 添加一个 delegate,在 text view 更新后调用 delegate,TableViewController 中收到 delegate 信息后更新 data。
修改后的 TextViewCell.h
|
1
2
3
4
5
6
7
8
9
|
#import <uikit uikit.h="">@protocol TextViewCellDelegate;@interface TextViewCell : UITableViewCell@property (weak, nonatomic) IBOutlet UITextView *textView;@property (weak, nonatomic) id<textviewcelldelegate> delegate;@end@protocol TextViewCellDelegate <nsobject>- (void)textViewCell:(TextViewCell *)cell didChangeText:(NSString *)text;@end</nsobject></textviewcelldelegate></uikit> |
在 TextView.m的 - (void)textViewDidChange:(UITextView *)textView 中添加 delegate 的调用
|
1
2
3
4
5
6
7
8
9
10
|
- (void)textViewDidChange:(UITextView *)textView{ if ([self.delegate respondsToSelector:@selector(textViewCell:didChangeText:)]) { [self.delegate textViewCell:self didChangeText:textView.text]; } // 计算 text view 的高度 ... // 让 table view 重新计算高度 ...} |
最后在 TableViewController.m 的最后实现 TextViewCellDelegate 的方法,更新 data
|
1
2
3
4
5
6
7
8
|
#pragma mark - TextViewCellDelegate- (void)textViewCell:(TextViewCell *)cell didChangeText:(NSString *)text{ NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; NSMutableArray *data = [self.data mutableCopy]; data[indexPath.row] = text; self.data = [data copy];} |
总结
从最后的代码量来看,这个功能在实现上并不难。只要记住的几点:
使用 iOS 8 的特性自动计算 cell 高度,或者在 heightForRow 中自己实现计算高度的代码。
UITextView 的 scrollEnable 要设置 NO
更新 table view 的高度使用 beginUpdates 和 endUpdates
Text view 更新内容后要保存数据,以免重新加载 cell 时数据丢失
参考
https://pontifex.azurewebsites.net/self-sizing-uitableviewcell-with-uitextview-in-ios-8/
http://stackoverflow.com/questions/50467/how-do-i-size-a-uitextview-to-its-content/26599389#26599389
http://stackoverflow.com/questions/18368567/uitableviewcell-with-uitextview-height-in-ios-7
iOS UITextView 输入内容实时更新cell的高度的更多相关文章
- MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新
MFC编辑框接收数据动态更新与刷新方法代码示例-如何让编辑框内容实时更新 关键代码: //发送数据通知 //from txwtech@163.com LRESULT CCommSampleDlg::O ...
- 【C#】让DataGridView输入中实时更新数据源中的计算列
本文适用Winform开发,且DataGridView的数据源为DataTable/DataView的情况. 理解前提:熟知DataTable.DataView 求:更好方案 考虑这样一个场景: 某D ...
- iOS 依据文本内容为TextView动态定义高度
解决方式: 1.定义一个textview,在storyboard中设定该textview的constraints. 2.将高度的constraint定义到头文件里:(直接拖拽) @property ( ...
- iOS之UITableView加载网络图片cell自适应高度
#pragma mark- UITableView - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSI ...
- IOS UITextView支持输入、复制、粘贴、剪切自定义表情
UITextView是ios的富文本编辑控件,除了文字还可以插入图片等.今天主要介绍一下UITextView对自定义表情的处理. 1.首先识别出文本中的表情文本,然后在对应的位置插入NSTextAtt ...
- [iOS] 输入框高度随输入内容变化
一般,类似聊天软件的输入框默认都是显示一行的,在用户输入过程中根据输入文字的内容来改变输入框的高度,以便显示全部文字.像微信,QQ的输入框就是这样的.那么这个效果应该怎么实现呢? 新博客:wosson ...
- iOS开发-UITextView根据内容自适应高度
UITextView作为内容文本输入区域,有的时候我们需要根据内容动态改变文本区域的高度,效果如下: 定义UITextView,实现UITextViewDelegate: -(UITextView * ...
- iOS学习网站及大牛网址(实时更新)
iOS学习网站及大牛网址(实时更新) 学习网站 https://github.com/Tim9Liu9/TimLiu-iOS 自己总结的iOS.mac开源项目及库 https://github.co ...
- iOS回顾笔记(09) -- Cell的添加、删除、更新、批量操作
iOS回顾笔记(09) -- Cell的添加.删除.更新.批量操作 项目中经常有对UITableViewCell做各种操作的需求: 添加一个新的cell 删除某行cell 刷新cell上某行数据(如修 ...
随机推荐
- HTML5学习笔记3 内联SVG
HTML5支持内联SVG 下面来介绍一下什么是SVG SVG可缩放矢量图形 可缩放矢量是基于可扩展标记语言(标准通用语言的子集),用于描述二维矢量图形的一种图形格式.它由万维网联盟制定,是一个开放标准 ...
- 常用排序算法及Java实现
概述 在计算器科学与数学中,一个排序算法(英语:Sorting algorithm)是一种能将一串数据依照特定排序方式进行排列的一种算法.本文将总结几类常用的排序算法,包括冒泡排序.选择排序.插入排序 ...
- GitHub的Fork 是什么意思
现在有这样一种情形: 有一个叫做Joe的程序猿写了一个游戏程序,而你可能要去改进它.并且Joe将他的代码放在了GitHub仓库上. 下面是你要做的事情 fork并且更新GitHub仓库的图表演示 Fo ...
- 【LeetCode】Sort Colors 解题报告
[题目] Given an array with n objects colored red, white or blue, sort them so that objects of the same ...
- IoC容器Autofac学习笔记
一.一个没有使用IoC的例子 IoC的全称是Inversion of Control,中文叫控制反转.要理解控制反转,可以看看非控制反转的一个例子. public class MPGMovieList ...
- Linux网络流量监控与分析工具Ntopng
Ntopng工具 Ntopng是一个功能强大的流量监控.端口监控.服务监控管理系统 能够实现高效地监控多台服务器网络 Ntopng功能介绍 Ntop提供了命令行界面和web界面两种工作方式,通过web ...
- 设计模式_Observable与Observer
一.基本概念 java.util.Observable 被观察者类,需要继承这个类 java.util.Observer 观察者类,需要实现这个接口中的update()方法 二.举例 Door ...
- ToStringBuilder学习(一):常用方法介绍
一.简介与引入 1.ToStringBuilder.HashCodeBuilder.EqualsBuilder.ToStringStyle.ReflectionToStringBuilder.C ...
- CodeForces 584D Dima and Lisa
1e9 以内的判断一个数是否是素数,可以直接朴素的暴力. 这倒题除了考虑1e9以内的素数的判断,还有一个歌德巴赫猜想:任意一个奇数都可一分解为三个素数的和. 第三个结论:素数是密集的,1e9以内, ...
- EMMC与nand flash的区别
1.NAND Flash 是一种存储介质,要在上面读写数据,外部要加主控和电路设计. 2.eMMC是NAND flash+主控IC ,对外的接口协议与SD.TF卡类似:对厂家而言简化了电路设计,降低了 ...