Вопрос

Я пытаюсь измерить визуальный размер строки 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?

Это было полезно?

Решение

Вместо 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.

Другие советы

Используйте sizeToFit UILabel вместо sizeWithFont: для размещения многострочного UILabel, так как sizeWithFont: будет обрезать строку (см. документацию Apple). Следующий код уменьшает размер шрифта надписи до тех пор, пока текст не уместится в указанный размер ... будет использовано несколько строк текста, как только они уместятся в указанную высоту:

-(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 будет использовать действительно маленькие шрифты.

edit: bugfix

Вместо того, чтобы пытаться сделать это за один вызов, сделайте что-то вроде этого (простите за псевдокод, уже поздно):

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

}

Правильный ответ, конечно, заключается в том, что вы должны установить numberOfLines в 0, что заставит каркас вычислять результат с тем количеством строк, которое ему нужно. См. Также этот вопрос .

Конечно, это не принимается во внимание, так как ничего не вызывается и не передается. Вы строго работаете со строками, размерами и шрифтами. Это метка с количеством строк.

Я не уверен, в чем именно твоя проблема; Вы получаете размер, который слишком высок или слишком короток, или что? Вы можете узнать количество строк текста, разделив высоту результата на высоту шрифта, которая, как я полагаю, является значением по возрастанию плюс по убыванию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top