【问题标题】:boundingRectWithSize not replicating UITextViewboundingRectWithSize 不复制 UITextView
【发布时间】:2016-05-13 13:27:02
【问题描述】:

我在一个项目中的要求是UITextView的字体大小应该根据UITextView的内容而减小。所以我正在尝试使用boundingRectWithSize 来估计文本的大小。

问题是我得到的字体有点太大了,有些部分的文字确实被剪掉了。

我的功能:

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

【问题讨论】:

    标签: ios objective-c ios7


    【解决方案1】:

    我在尝试做同样的事情时遇到了同样的问题。

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

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

    首先,textContainer.lineFragmentPadding:您可能已经注意到,您的尺寸通常总是偏离10px,这是因为系统默认值为5px。在计算估计尺寸时,您需要从要检查的尺寸中减去该值,并在得到最终值时将其加回。

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

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

    - (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 只是我编写的一个自定义函数,它将CGSizewidthheight 舍入到最近的0.5

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

    对于你关于计算合适的 pointSize 的问题,这是一些伪代码:

    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;
    

    同样,以上是基于我的实现的伪代码(不意味着只是替换你所拥有的)。希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      这样试试

      UITextView *textViewObj;//initialise textview.  
      
      textViewObj.autoresizesSubviews = NO;
      textViewObj.autoresizingMask = UIViewAutoresizingNone;
      

      【讨论】:

        【解决方案3】:

        这真的在 swift 中工作,获取 textview 的原始高度.. 试试这个 让

        size = cellQueue.contentLbl.sizeThatFits(CGSizeMake(cellQueue.contentLbl.frame.size.width,CGFloat(MAXFLOAT))) cellQueue.heightConstraintContentLbl.constant = size.height
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-13
          • 1970-01-01
          • 1970-01-01
          • 2014-05-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多