如何根据文本计算TextView高度

时间:2016-09-01 10:00:45

标签: ios uitextview

我使用下面的代码计算文字的高度,然后为UILabelUITextView设置此高度

CGSize targetSize = CGSizeMake(300, CGFLOAT_MAX);
NSString *message = @"The Internet connection appears to be offline.";

NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize boundingBox = [message boundingRectWithSize:targetSize
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                           attributes:@{NSFontAttributeName:FontOpenSanWithSize(14)}
                                              context:context].size;

CGSize size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
// it will return size:width = 299 and size height 20
// => if I use this height and set for UILabel, it can display full content
// => if I use this height and set for UITextView, it can not display full content 

它适用于UILabel,但UITextView某些时候计算错误。
我认为问题发生的原因是UITextView的填充(左,右)大于UILabel
那么如何计算正确的文本大小以便在UITextView中显示。任何帮助或建议将非常感谢。

如下图所示 使用相同的大小(300),相同的字体,相同的文本,但{2}行显示UITextView,但1行中的UILabel。 我的计算高度代码返回20,不足以显示2行,因此UITextView无法显示完整内容

我需要根据文字计算UITextView的高度,因为我的UITextView位于弹出式窗口中。 弹出窗口高度取决于TextView高度

enter image description here

6 个答案:

答案 0 :(得分:8)

您可以尝试两件事:

  1. 设置textView.textContainerInset = UIEdgeInsetsZero
  2. 设置textView.textContainer.lineFragmentPadding = 0
  3. 通过这些操作,你可以摆脱textView中的所有填充,当它的宽度与标签的宽度匹配时,高度也是相同的。

    以下是一个示例代码,您可以将其置于空的viewController中并自行测试:

    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
    
        NSString *text = @"The internet connection appears to be offline.";
        CGFloat width = 100.f;
    
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 20, width, 300)];
        textView.font = [UIFont fontWithName:@"AvenirNext-Regular" size:12.f];
        textView.text = text;
        [self.view addSubview:textView];
    
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20 + width, 20, width, 300)];
        label.numberOfLines = 0;
        label.font = [UIFont fontWithName:@"AvenirNext-Regular" size:12.f];
        label.text = text;
        [self.view addSubview:label];
    
        // Getting rid of textView's padding
        textView.textContainerInset = UIEdgeInsetsZero;
        textView.textContainer.lineFragmentPadding = 0;
    
        // Setting height of textView to its contentSize.height
        CGRect textViewFrame = textView.frame;
        textViewFrame.size = textView.contentSize;
        textView.frame = textViewFrame;
    
        // Setting height of label accorting to it contents and width
        CGRect labelFrame = label.frame;
        labelFrame.size = [label sizeThatFits:CGSizeMake(width, HUGE_VALF)];
        labelFrame.size.width = width;
        label.frame = labelFrame;
    
        NSLog(@"Label bounds: %@", NSStringFromCGRect(label.bounds));
        NSLog(@"TextView bounds: %@", NSStringFromCGRect(textView.bounds));
    
        // Visualizing final effect with borders
        textView.layer.borderColor = [UIColor redColor].CGColor;
        textView.layer.borderWidth = 1.f;
        label.layer.borderColor = [UIColor greenColor].CGColor;
        label.layer.borderWidth = 1.f;
    }
    

    控制台输出:

    2016-09-01 14:29:06.118 stack39268477[943:243243] Label bounds: {{0, 0}, {100, 66}}
    2016-09-01 14:29:06.119 stack39268477[943:243243] TextView bounds: {{0, 0}, {100, 66}}
    

答案 1 :(得分:6)

您不需要根据文字计算UITextview的高度。

只需更改框架并设置高度:

textview.size.height = textview.contentSize.height;

这是一个简单的解决方案。我希望这会对你有所帮助。

答案 2 :(得分:3)

快捷键5

一个我常用的经典技巧是创建一个将if re.search('(?i)Sepete Ekle', req1.text): print('White Royal Checked STOCKED!!!') else: print('White Royal Checked NOSTOCK') 作为参数的函数。在函数内,它会生成一个标签,该标签具有所需的宽度,无限的行数和“太多”的高度。然后在标签上加上String,然后返回框架的高度。

sizeToFit()

返回的高度可以应用于func calculatedHeight(for text: String, width: CGFloat) -> CGFloat { let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude)) label.numberOfLines = 0 label.text = text label.sizeToFit() return label.frame.height } 高度锚点。尽管我建议您根据屏幕尺寸动态计算宽度,但这取决于您。

答案 3 :(得分:2)

这会计算任何字符串的大小,无论您是否将它们放在文本视图中。

let frame = NSString(string: yourText).boundingRect(
    with: CGSize(width: yourDesiredWidth, height: .infinity),
    options: [.usesFontLeading, .usesLineFragmentOrigin],
    attributes: [.font : yourFont],
    context: nil)

let height = frame.size.height

答案 4 :(得分:1)

这里的大多数答案都是正确方向的提示: - )

所以,只是总结一下......

UITextView 使用 NSTextContainer (在私有API _UITextContainerView中)进行真正的布局工作。 此NSTextContainer(View)可能具有对周围UITextView的插入,这些插件由UITextView的 textContainerInset 属性设置。 此insets的默认值似乎是:

  • 顶部: 8
  • 左: 0
  • 底部: 8
  • 右: 0

NSTextContainer本身可能还有文本本身的左右插入。这些插入在NSTextContainer的 lineFragmentPadding 属性中设置。

  • 默认值为 5.0

因此,在根据UITextView中某些文本的boundingRect计算 UITextView 的最佳帧大小时,我们必须考虑所有这些插入内容:

db.collection('myCollection').where('sum_field1_field2','<',1000)
祝你好运: - )

答案 5 :(得分:0)

self.textView.textContainerInset = UIEdgeInsets.zero self.textView.textContainer.lineFragmentPadding = 0

在storyboard或xib标记textview height&gt; = 0。

如果您使用带有表格视图的文本视图。 根据内容计算单元格高度,textview将调整它的空间。