是否有一个好的方法来调整UITextView的大小以符合其内容?例如,我有一个包含一行文本的UITextView:
"Hello world"
然后我添加了另一行文本:
"Goodbye world"
在Cocoa Touch中是否有一个好的方法来获取矩形来保存文本视图中的所有行,这样我就可以相应地调整父视图?
另一个例子是,查看Calendar应用程序中用于事件的notes字段——注意单元格(以及它包含的UITextView)如何展开以保存notes字符串中的所有文本行。
是否有一个好的方法来调整UITextView的大小以符合其内容?例如,我有一个包含一行文本的UITextView:
"Hello world"
然后我添加了另一行文本:
"Goodbye world"
在Cocoa Touch中是否有一个好的方法来获取矩形来保存文本视图中的所有行,这样我就可以相应地调整父视图?
另一个例子是,查看Calendar应用程序中用于事件的notes字段——注意单元格(以及它包含的UITextView)如何展开以保存notes字符串中的所有文本行。
当前回答
更新
你需要做的关键事情是关闭UITextView中的滚动。
myTextView.scrollEnabled = @NO
原来的答案
要在UITableViewCell中创建一个动态大小的UITextView,我发现以下组合在Xcode 6和iOS 8 SDK中有效:
Add a UITextView to a UITableViewCell and constrain it to the sides Set the UITextView's scrollEnabled property to NO. With scrolling enabled, the frame of the UITextView is independent of its content size, but with scrolling disabled, there is a relationship between the two. If your table is using the original default row height of 44 then it will automatically calculate row heights, but if you changed the default row height to something else, you may need to manually switch on auto-calculation of row heights in viewDidLoad: tableView.estimatedRowHeight = 150; tableView.rowHeight = UITableViewAutomaticDimension;
对于只读动态大小的uitextview,就是这样。如果你允许用户在你的UITextView中编辑文本,你还需要:
实现UITextViewDelegate协议的textViewDidChange:方法,并告诉tableView在每次文本被编辑时重新绘制自己: - (void)textViewDidChange:(UITextView *)textView; { [tableView beginUpdates]; [tableView endUpdates]; } 别忘了在某个地方设置UITextView委托,在Storyboard或者tableView:cellForRowAtIndexPath:
其他回答
根据我有限的经验,
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
不尊重换行符,所以你最终可以得到比实际需要的更短的CGSize。
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
看起来很尊重换行符。
同样,文本也不是在UITextView顶部渲染的。在我的代码中,我将UITextView的新高度设置为比sizeOfFont方法返回的高度大24个像素。
我回顾了所有的答案,所有都保持固定的宽度和调整只有高度。如果你想调整宽度,你可以很容易地使用这个方法:
当配置文本视图时,将滚动设置为禁用
textView.isScrollEnabled = false
然后在委托方法func textViewDidChange(_ textView: UITextView)添加以下代码:
func textViewDidChange(_ textView: UITextView) {
let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}
输出:
对我来说最简单的解决方案是在Storyboard的textView上放一个高度约束,然后将textView和高度约束连接到代码:
@IBOutlet var myAwesomeTextView: UITextView!
@IBOutlet var myAwesomeTextViewHeight: NSLayoutConstraint!
然后在设置文本和段落样式后,在viewDidAppear中添加这个:
self.myAwesomeTextViewHeight.constant = self.myAwesomeTextView.contentSize.height
一些注意事项:
与其他解决方案相比,必须将isScrollEnabled设置为true才能使其工作。 在我的例子中,我在代码中设置自定义属性的字体,因此我必须在viewDidAppear中设置高度(在此之前它不会正常工作)。如果你没有在代码中更改任何文本属性,你应该能够在viewDidLoad或设置文本后的任何地方设置高度。
基于Nikita Took的回答,我想出了以下解决方案,适用于iOS 8的自动布局:
descriptionTxt.scrollEnabled = false
descriptionTxt.text = yourText
var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
for c in descriptionTxt.constraints() {
if c.isKindOfClass(NSLayoutConstraint) {
var constraint = c as! NSLayoutConstraint
if constraint.firstAttribute == NSLayoutAttribute.Height {
constraint.constant = contentSize.height
break
}
}
}
我会在页面底部发布正确的解决方案,以防有人勇敢(或绝望)读到这一点。
这里是那些gitHub回购,谁不想读所有的文本:resizableTextView
这适用于iOs7(我相信它将适用于iOs8)和自动布局。你不需要魔法数字,禁用布局之类的东西。简洁优雅的解决方案。
我认为,所有约束相关的代码都应该去updateConstraints方法。让我们创建自己的ResizableTextView。
我们在这里遇到的第一个问题是在viewDidLoad方法之前不知道真实的内容大小。我们可以根据字体大小、换行等进行计算。但我们需要稳健的解决方案,所以我们会:
CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];
现在我们知道真实的contentSize,不管我们在哪里:在viewDidLoad之前还是之后。现在在textView上添加高度约束(通过storyboard或代码,无论如何)。我们用contentSize.height来调整这个值:
[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = contentSize.height;
*stop = YES;
}
}];
最后要做的事情是告诉超类updateConstraints。
[super updateConstraints];
现在我们的类看起来是这样的:
ResizableTextView.m
- (void) updateConstraints {
CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];
[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = contentSize.height;
*stop = YES;
}
}];
[super updateConstraints];
}
又漂亮又干净,对吧?你不需要在控制器中处理这些代码!
但是等等! 没有动画!
你可以很容易地动画变化,使textView伸展顺利。这里有一个例子:
[self.view layoutIfNeeded];
// do your own text change here.
self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
[self.infoTextView setNeedsUpdateConstraints];
[self.infoTextView updateConstraintsIfNeeded];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
[self.view layoutIfNeeded];
} completion:nil];