如何调整UITextView的内容大小?

ios cocoa-touch autolayout uikit uitextview

361581 观看

30回复

6362 作者的声誉

是否有一个很好的方法来调整a的大小UITextView以使其内容符合?假设我有一个UITextView包含一行文本的:

"Hello world"

然后添加另一行文本:

"Goodbye world"

在Cocoa Touch中,有没有一种好的方法来rect保持文本视图中的所有行,以便我可以相应地调整父视图?

再举一个例子,在Calendar应用程序中查看便笺字段中的事件-注意单元格(及其UITextView包含的内容)如何扩展以容纳便笺字符串中的所有文本行。

作者: drewh 的来源 发布者: 2008 年 9 月 8 日

回应 (30)


12

5968 作者的声誉

你尝试了[textView sizeThatFits:textView.bounds]吗?

编辑:sizeThatFits返回大小,但实际上不调整组件的大小。我不确定这是您想要的,还是[textView sizeToFit]更多您想要的。无论哪种情况,我都不知道它是否完全适合您想要的内容,但这是尝试的第一件事。

作者: Mike McMaster 发布者: 08.09.2008 08:36

9

146 作者的声誉

另一种方法是使用该NSString方法查找特定字符串将占用的大小:

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

这将返回适合给定字符串和给定字体的矩形的大小。输入具有所需宽度和最大高度的大小,然后您可以查看返回的高度以适合文本。有一个版本可以让您指定换行模式。

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

作者: Code Addict 发布者: 20.09.2008 06:19

6

18637 作者的声誉

结合Mike McMaster的答案,您可能想要执行以下操作:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}
作者: Olie 发布者: 06.11.2008 04:31

24

251 作者的声誉

以我(有限)的经验,

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

不尊重换行符,因此您最终会CGSize比实际需要的短很多。

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

似乎确实尊重换行符。

此外,文字实际上并未呈现在的顶部UITextView。在我的代码中,我将的新高度设置为UITextViewsizeOfFont方法返回的高度大24个像素。

作者: user63934 发布者: 08.02.2009 07:01

1

27 作者的声誉

希望这可以帮助:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}
作者: Dr. Marty 发布者: 17.03.2010 05:31

576

14747 作者的声誉

这在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 通常是通过将属性链接到情节提要中创建的高度约束,通过IBOutlet设置的布局约束。


如果要添加一个惊人的答案,2014年,如果您:

[self.textView sizeToFit];

iPhone6 +的行为有所不同:

在此处输入图片说明

仅使用6+(而不是5s或6),它确实向UITextView添加了“多一个空白行”。“ RL解决方案”可完美解决此问题:

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

它解决了6岁以上的“额外排队”问题。

作者: Ronnie Liew 发布者: 21.03.2010 02:26

6

71 作者的声誉

我发现了一种方法,可以根据其中的文本来调整文本字段的高度,并根据文本字段的高度在其下方排列标签!这是代码。

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];
作者: dheeraj 发布者: 14.03.2011 10:13

1

631 作者的声誉

如果有其他人到达此解决方案,那么该解决方案对我有用:1“ Ronnie Liew” +4“ user63934”(我的文字来自网络服务):请注意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;

那就是...干杯

作者: Alejo JM 发布者: 30.07.2012 01:56

4

572 作者的声誉

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

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

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

    而(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);
}
作者: Bill Cheswick 发布者: 08.10.2012 05:59

8

13986 作者的声誉

如果您UITextView不方便使用(例如,您要调整表格视图单元的大小),则必须通过测量字符串来计算大小,然后在的两边考虑8 pt的填充UITextView。例如,如果您知道所需的文本视图宽度,并想找出相应的高度:

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高度。这会在您的文本下方添加一个空白行,如果在文本视图的正下方有视觉上较重的控件,则可能会看起来更好。

作者: Brent Royal-Gordon 发布者: 24.10.2012 11:20

1

3953 作者的声誉

我发现了根据文本大小重新调整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];
作者: Manju 发布者: 06.09.2013 06:27

22

15085 作者的声誉

在iOS6中,您可以contentSize在设置文本后立即检查UITextView 的属性。在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;
    }
}
作者: phatmann 发布者: 16.09.2013 09:35

3

3010 作者的声誉

对于iOS 7.0,不要将设置frame.size.heightcontentSize.height(当前不执行任何操作)use [textView sizeToFit]

看到这个问题

作者: Stian Høiland 发布者: 20.09.2013 02:39

599

6899 作者的声誉

决定

这适用于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中使用(在iOS 11中与Swift 4.1配合使用)

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

如果要支持iOS 6.1,则还应该:

textview.scrollEnabled = NO;
作者: jhibberd 发布者: 21.09.2013 10:26

18

3688 作者的声誉

我会在页面底部发布正确的解决方案,以防有人胆怯(或感到绝望)来阅读这一点。

这是那些不想阅读所有文本的gitHub存储库:resizableTextView

这适用于iOs7(我相信它将与iOs8一起使用)和自动布局。您不需要魔术数字,禁用布局之类的东西。简短而优雅的解决方案。

我认为,所有与约束相关的代码都应使用updateConstraints方法。因此,让我们自己做吧ResizableTextView

我们在这里遇到的第一个问题是在viewDidLoad方法之前不知道实际内容的大小。我们可以走很长的越野车,并根据字体大小,换行符等进行计算。但是我们需要可靠的解决方案,因此我们将这样做:

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

因此,无论我们身在何处,我们现在都知道真实的contentSize:before或after 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];

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

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];
作者: Nikita Took 发布者: 25.07.2014 07:32

90

2357 作者的声誉

为了UITextView在内部动态调整尺寸UITableViewCell,我发现以下组合可在Xcode 6和iOS 8 SDK中使用:

  • 将a添加UITextView到a UITableViewCell并将其约束到侧面
  • UITextViewscrollEnabled属性设置为NO。启用滚动功能后,的框架与UITextView内容大小无关,但是禁用滚动功能后,两者之间存在关联。
  • 如果您的表格使用的是原始的默认行高44,它将自动计算行高,但是如果您将默认行高更改为其他值,则可能需要在以下位置手动启用行高的自动计算功能viewDidLoad

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

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

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

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
    
  • 并且不要忘记将UITextView委托设置在某处Storyboard或某处tableView:cellForRowAtIndexPath:

作者: Brett Donald 发布者: 28.10.2014 01:12

1

1805 作者的声誉

对于那些希望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);
}
作者: Gal Blank 发布者: 30.11.2014 09:43

6

461 作者的声誉

那些使用自动版式和您的sizetofit的家伙无法正常工作,请检查一下您的宽度约束。如果您错过了宽度限制,那么高度将是准确的。

无需使用任何其他API。只需一行即可解决所有问题。

[_textView sizeToFit];

在这里,我只关心高度,保持宽度固定,并且错过了故事板中TextView的宽度约束。

这是为了显示服务中的动态内容。

希望这会有所帮助..

作者: Swaroop S 发布者: 02.01.2015 06:58

4

21991 作者的声誉

这是@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
作者: Fareed Alnamrouti 发布者: 07.03.2015 04:02

1

428 作者的声誉

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

作者: Mohammad Zekrallah 发布者: 08.04.2015 08:25

1

4790 作者的声誉

基于Nikita Took的回答,我来到了Swift中的以下解决方案,该解决方案可在具有自动布局的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
            }
        }
    }
作者: Apfelsaft 发布者: 13.05.2015 12:46

1

5340 作者的声誉

快速答案:以下代码计算了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)))

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

作者: RawMean 发布者: 16.05.2015 11:16

6

1748 作者的声誉

从iOS 8开始,可以使用UITableView的自动布局功能自动调整UITextView的大小,而无需任何自定义代码。我在github中放置了一个项目来演示此操作,但这是关键:

  1. UITextView必须禁用滚动,您可以通过编程或通过界面生成器来进行滚动。如果启用了滚动,则不会调整大小,因为滚动使您可以查看较大的内容。
  2. 在UITableViewController的viewDidLoad中,您必须为EstimateRowHeight设置一个值,然后将设置rowHeightUITableViewAutomaticDimension

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. 项目部署目标必须是iOS 8或更高版本。
作者: Chuck Krutsinger 发布者: 04.06.2015 05:41

58

4282 作者的声誉

斯威夫特:

textView.sizeToFit()
作者: Juan Boero 发布者: 01.10.2015 06:32

7

36817 作者的声誉

以下内容就足够了:

  1. 只记得将您的滚动启用设置为NOUITextView

在此处输入图片说明

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

您甚至可以使用UITableViewAutomaticDimension

作者: Bartłomiej Semańczyk 发布者: 02.11.2015 10:18

7

2259 作者的声誉

我们可以通过约束来做到这一点。

  1. 设置UITextView的高度限制。 在此处输入图片说明

2.为该高度约束创建IBOutlet。

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

}

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

作者: Kishore Kumar 发布者: 04.03.2016 07:16

61

12663 作者的声誉

同时使用代码和情节提要的非常简单的解决方案。

通过代码

textView.scrollEnabled = false

通过情节提要

取消选中滚动启用

在此处输入图片说明

除此以外,无需做任何其他事情。

作者: Alok 发布者: 17.07.2016 07:06

4

1435 作者的声誉

我查看了所有答案,所有答案均保持固定宽度,仅调整高度。如果您还希望调整宽度,则可以很容易地使用此方法:

因此在配置文本视图时,请禁用滚动

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

输出:

在此处输入图片说明

在此处输入图片说明

作者: Peter Stajger 发布者: 21.03.2017 01:38

1

116 作者的声誉

这是答案,如果您需要调整大小textViewtableViewCell动态调整staticTableView

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

作者: Volodymyr Nazarkevych 发布者: 31.03.2017 09:39

4

2304 作者的声誉

禁用滚动

添加内容

并添加文字

[yourTextView setText:@"your text"];
[yourTextView layoutIfNeeded];

如果使用,UIScrollView也应该添加它;

[yourScrollView layoutIfNeeded];

-(void)viewDidAppear:(BOOL)animated{
    CGRect contentRect = CGRectZero;

    for (UIView *view in self.yourScrollView.subviews) {
         contentRect = CGRectUnion(contentRect, view.frame);
    }
    self.yourScrollView.contentSize = contentRect.size;
}
作者: alicanozkara 发布者: 10.01.2018 01:06
32x32