有没有好的办法调整a的大小 UITextView 以符合其内容?比如说我有一个 UITextView 包含一行文本:

"Hello world"

然后我添加另一行文本:

"Goodbye world"

Cocoa Touch 有没有好的方法来获取 rect 这将保留文本视图中的所有行,以便我可以相应地调整父视图?

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

有帮助吗?

解决方案

这适用于 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;

其他提示

这不再适用于 iOS 7 或更高版本

实际上有一种非常简单的方法可以调整大小 UITextView 到内容的正确高度。可以使用以下方法完成 UITextView contentSize.

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

需要注意的一件事是,正确的 contentSize 仅可用 UITextView 已添加到视图中 addSubview. 。在此之前它等于 frame.size

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

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

heightConstraint 是一个布局约束,您通常通过 IBOutlet 设置该约束,方法是将属性链接到故事板中创建的高度约束。


只是为了补充这个令人惊奇的答案,2014 年,如果您:

[self.textView sizeToFit];

行为上与 iPhone6+ 仅有的:

enter image description here

仅对于 6+(不是 5s 或 6),它确实向 UITextView 添加了“一个空行”。“RL 解决方案”完美地解决了这个问题:

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

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

进行动态调整大小 UITextView 里面一个 UITableViewCell, ,我发现以下组合在 Xcode 6 和 iOS 8 SDK 中有效:

  • 添加一个 UITextView 到一个 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:

斯威夫特:

textView.sizeToFit()

使用代码和故事板的非常简单的工作解决方案。

通过代码

textView.scrollEnabled = false

通过故事板

取消选中 滚动启用

enter image description here

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

根据我(有限的)经验,

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

不尊重换行符,所以你可能会得到更短的结果 CGSize 比实际需要的多。

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

似乎确实尊重换行符。

此外,文本实际上并未呈现在顶部 UITextView. 。在我的代码中,我设置了新的高度 UITextView 比返回的高度大 24 像素 sizeOfFont 方法。

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

我将在页面底部发布正确的解决方案,以防有人勇敢(或足够绝望)阅读到这一点。

这是 gitHub 存储库,适合那些不想阅读所有文本的人: 可调整大小的文本视图

这适用于 iOs7(我相信它也适用于 iOs8)和自动布局。你不需要神奇的数字、禁用布局之类的东西。 简短而优雅的解决方案。

我认为,所有与约束相关的代码都应该转到 updateConstraints 方法。那么,让我们自己做一个 ResizableTextView.

我们在这里遇到的第一个问题是之前不知道真实的内容大小 viewDidLoad 方法。我们可以采取漫长而有缺陷的道路,并根据字体大小、换行符等来计算它。但我们需要强大的解决方案,所以我们会这样做:

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

现在我们的类看起来像:

可调整大小的TextView.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];

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

编辑:sizeThatFits 返回尺寸,但实际上并不调整组件的大小。我不确定这是否是你想要的,或者 [textView sizeToFit] 更符合您的需求。无论哪种情况,我不知道它是否完全适合您想要的内容,但这是首先要尝试的事情。

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

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

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

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

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

以下几点就足够了:

  1. 只需记住设置即可 滚动启用 为您 UITextView:

enter image description here

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

你甚至可以使用 UITableViewAutomaticDimension.

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

  1. 设置 UITextView 的高度约束。enter image description here

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

}

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

结合迈克·麦克马斯特的回答,您可能想做类似的事情:

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

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

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

希望这可能有所帮助..

从 iOS 8 开始,可以使用 UITableView 的自动布局功能来自动调整 UITextView 的大小,而无需任何自定义代码。我已经将一个项目放入 github 这在实际中证明了这一点,但关键是:

  1. UITextView 必须禁用滚动,您可以通过编程方式或通过界面生成器来执行此操作。如果启用滚动,它不会调整大小,因为滚动可以让您查看更大的内容。
  2. 在UITableViewController的viewDidLoad中,您必须设置estimatedRowHeight的值,然后设置 rowHeightUITableViewAutomaticDimension.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. 项目部署目标必须是 iOS 8 或更高版本。

当我需要在 a 中制作文本时,这非常有效 UITextView 适合特定区域:

// The text must already be added to the subview, or contentviewsize will be wrong.

- (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;
    }
    if (pointSize != font.pointSize)
        NSLog(@"font down to %.1f from %.1f", pointSize, tv.font.pointSize);
}

这是 @jhibberd 的 swift 版本

    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

我查看了所有答案,所有答案都保持固定宽度并仅调整高度。如果您还想调整宽度,您可以非常轻松地使用此方法:

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

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

输出:

enter image description here

enter image description here

禁用滚动

添加约束

并添加您的文字

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

对于 iOS 7.0,无需设置 frame.size.heightcontentSize.height (目前什么也不做)使用 [textView sizeToFit].

这个问题.

希望这可以帮助:

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

如果有其他人到达这里,这个解决方案对我有用,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;

那就是...干杯

我发现根据文本大小重新调整 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);
}

唯一有效的代码是使用“SizeToFit”的代码,如上面 jhibberd 答案中所示,但实际上它不会拾取,除非您调用它 查看已出现 或将其连接到 UITextView 文本更改事件。

根据 Nikita Take 的回答,我在 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
            }
        }
    }

迅速回答:以下代码计算 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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top