5

我正在尝试测量考虑到我可以渲染的行数的 NSString 的视觉大小。但是, sizeWithFont 不考虑 numberOfLines 属性?因此,我的布局算法将所有内容都定位在低于实际需要的位置。

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
/// the follow code ignores numberOfLines and just tells me the size of the whole block.  
// I'd like it to be aware of numberOfLines
//
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
        lineBreakMode:UILineBreakModeWordWrap];

有谁知道如何使用 iPhone SDK 做到这一点?

4

5 回答 5

12

而不是 CGFLOAT_MAX 为您的文本计算的最大高度,尝试使用此获取一行的大小:

[_price.text sizeWithFont:_price.font].height

然后将其乘以您想要的最大行数,然后将其插入您限制自己的大小的高度。它可能看起来像这样:

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
CGFloat lineHeight = [_price.text sizeWithFont:_price.font].height;
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, lineHeight * _price.numberOfLines)
        lineBreakMode:UILineBreakModeWordWrap];

如果您曾经将行数设置为 0,请不要使用它,因为在这种情况下,您的最大高度将为 0;那么你应该使用 CGFLOAT_MAX 。

于 2009-10-06T05:38:48.147 回答
5

使用 UILabel 的 sizeToFit 而不是 sizeWithFont: 来布局多行 UILabel,因为 sizeWithFont: 会截断字符串(参见苹果文档)。以下代码会减小标签的字体大小,直到文本适合指定的大小...一旦适合指定的高度,就会使用多行文本:

-(void)setFontSizeOfMultiLineLabel: (UILabel*)label 
        toFitSize: (CGSize) size 
        forMaxFontSize: (CGFloat) maxFontSize 
        andMinFontSize: (CGFloat) minFontSize 
        startCharacterWrapAtSize: (CGFloat)characterWrapSize{

CGRect constraintSize = CGRectMake(0, 0, size.width, 0);
label.frame = constraintSize;
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0; // allow any number of lines

for (int i = maxFontSize; i > minFontSize; i--) {

    if((i < characterWrapSize) && (label.lineBreakMode == UILineBreakModeWordWrap)){
        // start over again with lineBreakeMode set to character wrap 
        i = maxFontSize;
        label.lineBreakMode = UILineBreakModeCharacterWrap;
    }

    label.font = [label.font fontWithSize:i];
    [label sizeToFit];
    if(label.frame.size.height < size.height){
        break;
    }       
    label.frame = constraintSize;
  } 
}

使用具有您喜欢的文本和字体的标签调用它:

UILabel *label = [[UILabel alloc] initWithFrame: CGRectZero];   
label.backgroundColor = [UIColor clearColor];   
label.textColor = [UIColor whiteColor];
label.text = text;
label.font = [UIFont fontWithName: @"Helvetica" size: 16];
[self setFontSizeOfMultiLineLabel: label toFitSize: CGSizeMake(200, 44) forMaxFontSize: 16 andMinFontSize: 8 startCharacterWrapAtSize: 11]; 

startCharacterWrapAtSize 参数允许您选择从给定字体大小开始使用 characterWrap。如果 wordWrap 使用非常小的字体,这应该可以节省空间。

编辑:错误修正

于 2010-08-30T08:53:37.257 回答
0

与其尝试一次调用,不如执行以下操作(请原谅伪代码,为时已晚):

NSString *s = _price.text;
UIFont *font = _price.font;
CGFloat fontSize = font.pointSize;

while (TRUE)
{
   CGSize priceSize = [s sizeWithFont: font constrainedToSize: 
       CGSizeMake(maxWidth, fontSize) lineBreakMode: UILineBreakModeWordWrap];

    if ( /* priceSize is satisfactory */ )
    {
        break; // Make sure this exits, eventually!!!
    }
    fontSize -= 1.0; // or a smaller decrement if you like
    font = // new, smaller font

}
于 2009-07-30T03:52:51.473 回答
0

正确的答案是,当然,您需要将 numberOfLines 设置为 0,这将导致框架使用所需的行数来计算结果。另请参阅此问题

于 2009-10-06T05:19:45.097 回答
-1

当然它没有考虑到它,因为没有任何被调用或传入的信息具有该信息。您正在严格使用字符串、大小和字体。它是包含行数的标签。

我不确定您的问题到底是什么;你的尺码太高或太短,还是什么?您可以通过将结果的高度除以字体的高度来找出文本的行数,我相信这是升序加降序的值。

于 2009-07-30T03:34:23.390 回答