boundingRectWithSize不复制UITextView [英] boundingRectWithSize not replicating UITextView

查看:78
本文介绍了boundingRectWithSize不复制UITextView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在项目中的要求是 UITextView 的字体大小应该根据 UITextView 的内容减少。所以我想用 boundingRectWithSize 来估算文本的大小。

My requirement in a project is that the font size of the UITextView should decrease according the content of the UITextView. So i am trying to do estimate the size of the text using boundingRectWithSize.

问题是我得到的字体有点太大,文本的某些部分会被剪裁。

The problem is that the font size I get is a bit too big and some part of the text does get clipped.

我的功能:

 -(BOOL)updateTextViewFontSizeForText:(NSString*)text{

    float fontSize = self.maximumFontSizeInPoints;

    self.font = [self.font fontWithSize:fontSize];

    CGSize tallerSize ;
    CGSize stringSize ;


    do
    {
        if (fontSize <= self.minimumFontSizeInPoints) // it just won't fit
            return NO;

        fontSize -= 1.0;
        self.font = [self.font fontWithSize:fontSize];

        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];

        NSDictionary *attributes = @{ NSFontAttributeName: self.font, NSParagraphStyleAttributeName : paragraphStyle };



        tallerSize = CGSizeMake(self.frame.size.width,self.frame.size.height-16);// the 16 is given because uitextview adds some offset
        stringSize = [text boundingRectWithSize:CGSizeMake(self.contentSize.width,CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
    }while(stringSize.height >= tallerSize.height);


    if ([self.onTextChangDelegate respondsToSelector:@selector(onTextChangDelegate)]) {

        [self.onTextChangDelegate onTextChanged:text];
    }

    return YES;
}


推荐答案

我遇到了同样的问题当试图做同样的事情时。

I ran into the same issue when trying to do the same thing.

问题是 UITextView 与boundingRectWithSize相比如何运行它的换行符。您可以在此处阅读更多详细信息: https:// developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextLayout/Concepts/CalcTextLayout.html

The issue is how UITextView run's its line-breaks compared to boundingRectWithSize. You can read more details here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextLayout/Concepts/CalcTextLayout.html

但你实际上可以算出确切的大小!基本上有两个 UITextView 的属性,为了获得正确的大小估计,您需要考虑这两个属性。第一个是 textContainer.lineFragmentPadding ,第二个是 textContainerInset

But you can actually calculate the exact size! There are basically two properties of a UITextView that you'll need to take into account in order to get correct size estimates. The first is textContainer.lineFragmentPadding, the second is textContainerInset.

首先, textContainer.lineFragmentPadding :您可能已经注意到您的尺寸通常始终是 10px ,这是因为系统默认值为 5px 。当您计算估计的大小时,您需要从您检查的大小中减去此值,并在获得最终值时将其重新添加。

First, textContainer.lineFragmentPadding: You may have noticed that your sizing is generally always off by 10px, this is because the systems default value is 5px. When you're calculating your estimated size, you'll need to subtract this value from the size you're checking against and add it back when you have your final value.

其次, textContainerInset 。这是一个 UIEdgeInset ,您需要将其添加回最终计算值以匹配系统。

Second, textContainerInset. This is a UIEdgeInset that you'll need to add back to your final calculated value to match the systems.

这是基于我如何解决问题的代码:

This is code based on how I solved the issue:

- (CGSize)sizeThatFits:(CGSize)size
    CGFloat lineFragmentPaddings = self.textContainer.lineFragmentPadding * 2;
    CGFloat horzPadding = self.textContainerInset.left + self.textContainerInset.right + lineFragmentPaddings;
    CGFloat vertPadding = self.textContainerInset.top + self.textContainerInset.bottom;

    size.width -= horzPadding;
    CGRect boundingRect = [attributedText boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin context:nil];
    size = boundingRect.size;
    // I found through debugging that adding 0.25 rounded
    // matches sizeThatFits: identically. Not sure why…
    size.width += horzPadding + 0.25;
    size.height += vertPadding + 0.25;
    size = CGSizeRound(size);

    return size;
}

注意, CGSizeRound 只是我编写的一个自定义函数,用于围绕 CGSize的 width height code>到最近的 0.5

Note, CGSizeRound is just a custom function I wrote that rounds the width and height of the CGSize to the nearest 0.5.

为了比较,如果你创建第二个 UITextView ,并确保 textContainer.lineFragmentPadding textContainerInset 相同,您应该看到几乎与最近的 0.5 相同的值。

For comparison, if you create a second UITextView, and make sure the textContainer.lineFragmentPadding and textContainerInset are the same, you should see the values almost identical to the nearest 0.5.

关于计算正确pointSize的问题,这是一些伪代码:

And to your question about calculating a proper pointSize, this is some pseudo code for that:

CGFloat pointSize = 64;
CGFloat minPointSize = 32;
CGFloat decrementor = 4;
CGFloat padding = self.textContainerInset.left + self.textContainerInset.right + lineFragmentPaddings;
CGFloat actualWidth = self.maxTextViewSize.width - padding * 2;
CGRect boundingRect = CGRectZero;
BOOL isValidPointSize = NO;
do {
    if (pointSize < minPointSize) {
        pointSize = minPointSize;
        boundingRect.size.height = self.maxTextViewSize.height;
        isValidPointSize = YES;
    } else {
        NSDictionary *defaultAttributes = [self.customTextStorage defaultAttributesForPointSize:pointSize];
        NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:defaultAttributes];

        boundingRect = [attrString boundingRectWithSize:CGSizeMake(actualWidth, 1024) options:NSStringDrawingUsesLineFragmentOrigin context:nil];
        // is the height to big?
        if (boundingRect.size.height > self.maxTextViewSize.height) {
            // reduce the point size for next iteration of loop
            pointSize -= decrementor;
        }
        // passes height test
        else {
            isValidPointSize = YES;
        }
    }
} while (!isValidPointSize);

return pointSize;

再次,上面是基于我的实现的伪代码(不仅仅意味着替换掉什么你有)。希望这有帮助!

Again, the above is pseudo code based on my implementation (not meant for just drop in replacement for what you have). Hope this helps!

这篇关于boundingRectWithSize不复制UITextView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆