如何调整UITextView的内容?

有一个好的方法来调整UITextView的大小以符合其内容? 说例如我有一个UITextView包含一行文本:

 "Hello world" 

然后我添加另一行文字:

 "Goodbye world" 

在Cocoa Touch中是否有一个很好的方法来获得将保存文本视图中所有行的rect ,以便我可以相应地调整父视图?

作为另一个例子,查看日历应用程序中事件的注释字段 – 注意单元格(以及它所包含的UITextView )如何扩展,以保存注释string中的所有文本行。

这适用于iOS 6.1和iOS 7:

 - (void)textViewDidChange:(UITextView *)textView { CGFloat fixedWidth = textView.frame.size.width; CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)]; CGRect newFrame = textView.frame; newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height); textView.frame = newFrame; } 

或者在Swift中

 let fixedWidth = textView.frame.size.width textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude)) let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude)) var newFrame = textView.frame newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height) textView.frame = newFrame 

如果你想支持iOS 6.1,那么你还应该:

 textview.scrollEnabled = NO; 

这不再适用于iOS 7或以上

实际上有一个非常简单的方法来调整UITextView的正确高度的内容。 它可以使用UITextView contentSize来完成。

 CGRect frame = _textView.frame; frame.size.height = _textView.contentSize.height; _textView.frame = frame; 

有一点需要注意的是正确的contentSize只有 UITextView通过addSubview添加到视图后才可用。 在此之前,它等于frame.size

如果自动布局为ON,这将不起作用。 对于自动布局,一般的方法是使用sizeThatFits方法并在高度约束上更新constant量值。

 CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size]; heightConstraint.constant = sizeThatShouldFitTheContent.height; 

heightConstraint是一个布局约束,您通常通过将属性链接到在故事板中创build的高度约束来通过IBOutlet进行设置。


只是为了增加这个惊人的答案,2014年,如果你:

 [self.textView sizeToFit]; 

只有在iPhone6 +的行为有所不同:

在这里输入图像描述

只有6+(不是5或6),它会在UITextView中增加一个“空白行”。 “RL解决scheme”完美地解决了这个问题:

 CGRect _f = self.mainPostText.frame; _f.size.height = self.mainPostText.contentSize.height; self.mainPostText.frame = _f; 

它修复了6+的“额外线路”问题。

为了在UITableViewCell创build一个dynamicresize的UITextView ,我在iOS 8 SDK中发现了Xcode 6中的以下组合:

  • UITextView添加到UITableViewCell并将其限制在边上
  • UITextViewscrollEnabled属性设置为NO 。 启用滚动function后, UITextView的框架与其内容大小无关,但禁用滚动function时,两者之间存在关系。
  • 如果您的表格使用的是原始的默认行高度44,那么它将自动计算行高度,但是如果将默认行高度更改为其他值,则可能需要手动打开viewDidLoad中行高的自动计算:

     tableView.estimatedRowHeight = 150; tableView.rowHeight = UITableViewAutomaticDimension; 

对于只读dynamic调整UITextView的大小,就是这样。 如果您允许用户编辑UITextView的文本,则还需要:

  • 实现UITextViewDelegate协议的textViewDidChange:方法,并在每次编辑文本时告诉tableView自己重绘:

     - (void)textViewDidChange:(UITextView *)textView; { [tableView beginUpdates]; [tableView endUpdates]; } 
  • 不要忘记设置UITextView委托的地方,在Storyboard或在tableView:cellForRowAtIndexPath:

Swift:

 textView.sizeToFit() 

在我(有限)的经历中,

 - (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

不尊重换行符,所以最终CGSize比实际需要的CGSize更短。

 - (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size 

似乎尊重换行符。

另外,文本实际上并不在UITextView的顶部。 在我的代码中,我将UITextView的新高度设置为比sizeOfFont方法返回的高度大24个像素。

在iOS6中,您可以在设置文本后立即检查UITextView的contentSize属性。 在iOS7中,这将不再起作用。 如果您想为iOS7恢复此行为,请将以下代码放在UITextView的子类中。

 - (void)setText:(NSString *)text { [super setText:text]; if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer]; UIEdgeInsets inset = self.textContainerInset; self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size; } } 

我会在页面的底部张贴正确的解决scheme,以防万一有人勇敢(或绝望地)读到这一点。

这里是gitHub回购为那些谁不想读取所有文本: resizableTextView

这与iOs7(我相信它会与iOs8一起工作)和自动布局一起工作。 你不需要神奇的数字,禁用布局和类似的东西。 简洁优雅的解决scheme。

我认为所有与约束有关的代码都应该去updateConstraints方法。 所以,我们来创build我们自己的ResizableTextView

我们遇到的第一个问题是,在viewDidLoad方法之前不知道真正的内容大小。 我们可以采取漫长的马路,并根据字体大小,换行符等进行计算。但是我们需要强大的解决scheme,所以我们要做:

CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

所以现在我们知道真正的contentSize,无论我们在哪里:在viewDidLoad之前或之后。 现在,添加高度约束textView(通过故事板或代码,无论如何)。 我们将使用contentSize.height调整该值:

 [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) { if (constraint.firstAttribute == NSLayoutAttributeHeight) { constraint.constant = contentSize.height; *stop = YES; } }]; 

最后要做的是告诉超类updateConstraints

 [super updateConstraints]; 

现在我们的class级看起来像:

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]; } 

漂亮干净,对吧? 而且您不必在控制器中处理该代码!

可是等等! 没有animation!

你可以很容易地animation变化,使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]; 

刚刚设置

 textView.scrollEnabled = false 

除此之外不需要做任何事情。

你有没有尝试[textView sizeThatFits:textView.bounds]

编辑:sizeThatFits返回的大小,但不实际调整组件大小。 我不确定这是你想要的,或者如果[textView sizeToFit]更多的是你要找的。 无论哪种情况,我都不知道它是否能够完美地符合你想要的内容,但是这是第一个尝试的方法。

另一种方法是使用NSString方法查找特定string将要占用的大小:

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

这将返回适合给定string的矩形的大小。 通过所需宽度和最大高度的尺寸,然后您可以查看返回的高度以适合文本。 有一个版本可以让你指定换行符模式。

然后,您可以使用返回的大小来更改视图的大小以适应。

如果你没有方便的UITextView (例如,你正在调整表格视图单元格大小),你将不得不通过测量string来计算大小,然后计算UITextView每边的8点填充。 例如,如果您知道文本视图的所需宽度并想要找出相应的高度:

 NSString * string = ...; CGFloat textViewWidth = ...; UIFont * font = ...; CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000); size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8; 

在这里,每个8是占四个填充边缘之一,而100000只是一个非常大的最大尺寸。

在实践中,您可能需要添加一个额外的font.leading到高度; 这会在文本下面添加一个空白行,如果在文本视图下方直接显示可视化控件,这可能会更好一些。

以下事情已经足够了:

  1. 只记得为你的UITextView设置滚动NO

在这里输入图像描述

  1. 正确设置自动布局约束。

你甚至可以使用UITableViewAutomaticDimension

我们可以通过约束来实现。

  1. 为UITextView设置高度约束。 在这里输入图像描述

2.创buildIBOutlet的高度约束。

  @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints; 

3.不要忘记为你的textview设置代表。

4。

 -(void)textViewDidChange:(UITextView *)textView { CGFloat fixedWidth = textView.frame.size.width; CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)]; CGRect newFrame = textView.frame; newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height); NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size)); [UIView animateWithDuration:0.2 animations:^{ _txtheightconstraints.constant=newFrame.size.height; }]; } 

然后像这样更新你的约束:)

结合迈克·麦克马斯特的回答,你可能想要做一些事情:

 [myTextView setDelegate: self]; ... - (void)textViewDidChange:(UITextView *)textView { if (myTextView == textView) { // it changed. Do resizing here. } } 

我发现了一种方法来根据文本里面的文本来调整文本字段的高度,并根据文本字段的高度在它下面安排一个标签! 这是代码。

 UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)]; NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different."; _textView.text = str; [self.view addSubview:_textView]; CGRect frame = _textView.frame; frame.size.height = _textView.contentSize.height; _textView.frame = frame; UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)]; lbl.text = @"Hello!"; [self.view addSubview:lbl]; 

使用自动布局和你的sizetofit不工作的人,那么请检查你的宽度约束一次。 如果你错过了宽度约束,那么高度将是准确的。

不需要使用任何其他的API。 只有一条线可以解决所有问题。

 [_textView sizeToFit]; 

在这里,我只关心高度,保持宽度不变,错过了Storyboard中TextView的宽度约束。

这是为了显示服务的dynamic内容。

希望这可能会帮助..

从iOS 8开始,可以使用UITableView的自动布局function来根据自定义代码自动调整UITextView的大小。 我已经在github上做了一个项目来certificate这一点,但这里是关键:

  1. UITextView必须禁用滚动function,您可以通过编程或通过界面生成器进行操作。 如果启用了滚动,则不会resize,因为滚动可以查看较大的内容。
  2. 在UITableViewController的viewDidLoad中,必须为estimatedRowHeight设置一个值,然后将rowHeight设置为UITableViewAutomaticDimension
 - (void)viewDidLoad { [super viewDidLoad]; self.tableView.estimatedRowHeight = self.tableView.rowHeight; self.tableView.rowHeight = UITableViewAutomaticDimension; } 
  1. 项目部署目标必须是iOS 8或更高版本。

这里是@jhibberd的快速版本

  let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell cell.msgText.text = self.items[indexPath.row] var fixedWidth:CGFloat = cell.msgText.frame.size.width var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max) var newSize:CGSize = cell.msgText.sizeThatFits(size) var newFrame:CGRect = cell.msgText.frame; newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height); cell.msgText.frame = newFrame cell.msgText.frame.size = newSize return cell 

当我需要使UITextView文本适合特定区域时,这很好地工作:

 //文本必须已经添加到子视图,否则contentviewsize将会出错。

 - (void)reduceFontToFit:(UITextView *)tv {
     UIFont * font = tv.font;
     double pointSize = font.pointSize;

     while(tv.contentSize.height> tv.frame.size.height && pointSize> 7.0){
         pointSize  -  = 1.0;
         UIFont * newFont = [UIFont fontWithName:font.fontName size:pointSize];
         tv.font = newFont;
     }
    如果(pointSize!= font.pointSize)
         NSLog(@“从%.1f到%.1f的字体”,pointSize,tv.font.pointSize);
 }

对于iOS 7.0,不是将frame.size.height设置为contentSize.height (目前什么都不做),而是使用[textView sizeToFit]

看到这个问题 。

我回顾了所有的答案,都保持固定的宽度,只调整高度。 如果你想调整宽度,你可以很容易地使用这种方法:

所以当configuration你的文本视图,设置滚动禁用

 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) } 

输出:

在这里输入图像描述

在这里输入图像描述

希望这可以帮助:

 - (void)textViewDidChange:(UITextView *)textView { CGSize textSize = textview.contentSize; if (textSize != textView.frame.size) textView.frame.size = textSize; } 

如果有任何其他的到这里,这个解决scheme为我工作,1“Ronnie Liew”+4“user63934”(我的文本从web服务到达):注意1000(在我的情况下,没有什么可以这么大)

 UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE]; NSString *dealDescription = [client objectForKey:@"description"]; //4 CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)]; CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height); UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease]; dealDesc.text = dealDescription; //add the subview to the container [containerUIView addSubview:dealDesc]; //1) after adding the view CGRect frame = dealDesc.frame; frame.size.height = dealDesc.contentSize.height; dealDesc.frame = frame; 

那就是……干杯

我发现根据文本的大小重新调整UITextView的高度的最佳方式。

 CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0] constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)]; 

或者你可以使用

 CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0] constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail]; 

对于那些希望textview实际上移动并保持底线位置的人

 CGRect frame = textView.frame; frame.size.height = textView.contentSize.height; if(frame.size.height > textView.frame.size.height){ CGFloat diff = frame.size.height - textView.frame.size.height; textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height); } else if(frame.size.height < textView.frame.size.height){ CGFloat diff = textView.frame.size.height - frame.size.height; textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height); } 

唯一能够工作的代码是在上面的jhibberd回答中使用“SizeToFit”的代码,但实际上,除非您在ViewDidAppear中调用它或将其连接到UITextView文本更改的事件,否则它将不会启动。

基于Nikita Took的回答,我来到了Swift中的以下解决scheme,该解决scheme使用自动布局在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 } } } 

Swift的答案:下面的代码计算你的textView的高度。

  let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX) let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin let attribute = [NSFontAttributeName: textView.font!] let str = NSString(string: message) let labelBounds = str.boundingRectWithSize(maximumLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: attribute, context: nil) let myTextHeight = CGFloat(ceilf(Float(labelBounds.height))) 

现在,您可以将myTextHeight的高度设置为myTextHeight

如果您需要在staticTableViewdynamic调整staticTableViewtableViewCell大小,这里是答案

[ https://stackoverflow.com/a/43137182/5360675%5D [1 ]

这个方法似乎适用于ios7

  // Code from apple developer forum - @Steve Krulewitz, @Mark Marszal, @Eric Silverberg - (CGFloat)measureHeight { if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) { CGRect frame = internalTextView.bounds; CGSize fudgeFactor; // The padding added around the text on iOS6 and iOS7 is different. fudgeFactor = CGSizeMake(10.0, 16.0); frame.size.height -= fudgeFactor.height; frame.size.width -= fudgeFactor.width; NSMutableAttributedString* textToMeasure; if(internalTextView.attributedText && internalTextView.attributedText.length > 0){ textToMeasure = [[NSMutableAttributedString alloc] initWithAttributedString:internalTextView.attributedText]; } else{ textToMeasure = [[NSMutableAttributedString alloc] initWithString:internalTextView.text]; [textToMeasure addAttribute:NSFontAttributeName value:internalTextView.font range:NSMakeRange(0, textToMeasure.length)]; } if ([textToMeasure.string hasSuffix:@"\n"]) { [textToMeasure appendAttributedString:[[NSAttributedString alloc] initWithString:@"-" attributes:@{NSFontAttributeName: internalTextView.font}]]; } // NSAttributedString class method: boundingRectWithSize:options:context is // available only on ios7.0 sdk. CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil]; return CGRectGetHeight(size) + fudgeFactor.height; } else { return self.internalTextView.contentSize.height; } }