引言:项目需求,类似实现微信输入框效果,用户输入文字时,输入框的高度自适应。自己实现的过程中,遇到了一些问题,特此记录一下。
使用UITextView来实现此需求,首先初始化UITextView的frame,然后实现UITextView的代理方法- (void)textViewDidChange:(UITextView *)textView;
,此方法当UITextView有输入就会调用,在此代理方法中重绘UITextView的frame,已达到高度自适应的要求,那么问题来了。
问题1:
在UITextView的特定frame中,如何判断什么时候换行?
解决1:使用计算字符串的方法,计算出其内容在给定的UITextView的宽度的范围内的高度,然后利用计算出的内容的高度加上适当的数值作为UITextView的高度。代码如下:
- (void)textViewDidChange:(UITextView *)textView{
NSString *testString = [NSString stringWithFormat:@"测试测试测试测试测试"];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[UIFont systemFontOfSize:16] forKey:NSFontAttributeName];
//此处的100 应为你的UITextView的宽度
CGSize testStringSize = [testString boundingRectWithSize:CGSizeMake(100, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:dict
context:nil].size;
//重绘UITextView的frame
CGRect rect = _textView.frame;
rect.frame.size = testStringSize;
_textView.frame = rect;
}
此种方法可以解决问题但是又引出了新的问题,使用此种方法,会出现本应该换行输入时,UITextView的高度并没有改变,而是再输入几个字符才会改变高度,这个问题我没有找到原因,搜索网络上,也有存在此问题的网友,如果您知道解决办法,请在下方留言,多谢!
解决2:
使用sizeThatFits或者sizeToFit方法解决此问题。
这两种方法存在的区别在于(个人理解):
1、sizeThatFits方法会返回最适合内容的当前接收者的宽度和高度,但是不会改变当前接收者的frame。
2、sizeToFit方法会返回最适合内容的当前接收者的宽度和高度,会直接改变当前接收者的frame;
注:
1、当前接收者为需要自适应高度的View,此处为UITextView。上述两个方法为UIView的方法,所以继承UIView的视图都可以使用。
代码如下:
- (void)textViewDidChange:(UITextView *)textView{
//1.计算textView文字高度
[_textView sizeToFit];
//CGSize size = [textView sizeThatFits:CGSizeZero];
//CGSize size = [textView sizeThatFits:CGSizeMake(80, 80)];
//2.重绘_textView宽度(因为这里使用的是sizeToFit方法,UITextView的实际frame已经改变了,所以需要重绘宽度)
CGRect rect = _textView.frame;
//TEXTVIEW_WIDTH为UITextView的固定宽度值
rect.size.width = TEXTVIEW_WIDTH;
_textView.frame = rect;
}
上述代码使用的方法为sizeToFit
需要重绘宽度,使用sizeThatFits方法与上述使用方式类似,这里就不赘述了。
但是需要注意的是:
1、当使用CGSizeZero
时,其返回的size为正常显示的size。
2、当你自定义某个size时,例如:CGSizeMake(80, 80)
,当计算的最合适的size比自定义的数值小时,返回正常计算的size,当计算的最合适的size比自定义的数值大时,这时返回的将是在自定义size范围内的最合适的size。
3、记得重绘视图的size,因为此方法并不会直接改变视图的size!