sizeWithFont не дает правильную высоту для UITextView, если в переносимом тексте есть длинная строка - PullRequest
15 голосов
/ 25 февраля 2010

Есть ли способ получить правильный размер строки NSString, используя:

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

, который не сбрасывается с 2 или 3 сотнями строк символов. В настоящий момент, если я пытаюсь использовать этот метод на этих длинных строках, он неправильно вычисляет их, и в итоге получается много пробелов в нижней части UITextView.

Я пытался использовать UILineBreakModeWordWrap и UILineBreakModeCharacterWrap.

изменение размера выполняется в

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat     result = 44.0f;
    NSString*   text = nil;
    CGFloat     width = 0;
    CGFloat     tableViewWidth;
    CGRect      bounds = [UIScreen mainScreen].bounds;

    tableViewWidth = bounds.size.width;


    width = tableViewWidth - 150;       

    text = stringWithLongWords;

    if (text) {
        CGSize      textSize = { width, 20000.0f };     
        CGSize      size = [text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];

        size.height += 50.0f;               
        result = MAX(size.height, 44.0f+30.0f); 
    }

    return result;
}

Ответы [ 6 ]

21 голосов
/ 05 марта 2010

UITextView не совсем как UILabel, завернутый в UIScrollView. Он имеет межстрочный интервал, отличный от размера шрифта, и полей, которые sizeWithFont:constrainedToSize:linkBreakMode: не учитывает.

Зная размер шрифта, вы сможете рассчитать количество строк и учесть расстояние между строками. Вы можете угадать на полях и попытаться обмануть sizeWithFont:, чтобы дать более полезный ответ.

Популярные решения:

  • просто используйте UILabel, если вам не нужна UITextView функциональность

  • если вам нужно hyperlinks, наложение UIButtons, которое выглядит как гиперссылка на UILabel

  • используйте закадровый UITextView и метод sizeToFit, чтобы получить реальный ответ

Мне не повезло с третьим вариантом, но, похоже, он должен работать, так что, возможно, я сделал что-то не так.

Я собираюсь попробовать использовать UILabel и наложения кнопок для гиперссылок. Посмотрим, как это получится.

Если это не удается, всегда есть вариант, выбранный Лорен Брихтер (из известности Tweetie): нарисовать все в UIView самостоятельно, используя CoreGraphics.

Удачи!

9 голосов
/ 21 октября 2010

Ознакомьтесь с этим сообщением Как изменить размер UITextView для его содержимого?

Похоже, что textView.contentSize.height должен работать (с оговоркой, что правильный contentSize доступен только после добавления UITextView в представление с addSubview)

1 голос
/ 05 декабря 2014

Ширина, которую вы используете, является шириной для вашего UITextView ... но вас не интересует эта ширина, вы беспокоитесь о ширине фактической текстовой области, вложенной в текстовое представление.

UITextViews, по умолчанию, имеют отступы вокруг своих границ, чтобы создать пространство между напечатанным текстом и краем UITextView шириной в несколько пикселей (и длинным для верха) ... не использую

textView.frame.size.width

а точнее,

textView.frame.size.width-(textView.contentInset.left+textView.contentInset.right+textView.textContainerInset.left+textView.textContainerInset.right+textView.textContainer.lineFragmentPadding/*left*/+textView.textContainer.lineFragmentPadding/*right*/)

^, который принимает ширину UITextView и вычитает все отступы, так что вы остаетесь с шириной только текстовой области с возможностью ввода.

То же самое относится и к высоте, за исключением того, что lineFragmentPadding не имеет дна, поэтому вы вычитаете его только один раз вместо двух.


Окончательный код выглядит примерно так:

    CGSize textViewContentSize = CGSizeMake(theTextView.frame.size.width-(theTextView.contentInset.left+theTextView.contentInset.right+theTextView.textContainerInset.left+theTextView.textContainerInset.right+theTextView.textContainer.lineFragmentPadding/*left*/+theTextView.textContainer.lineFragmentPadding/*right*/), theTextView.frame.size.height-(theTextView.contentInset.top+theTextView.contentInset.bottom+theTextView.textContainerInset.top+theTextView.textContainerInset.bottom+theTextView.textContainer.lineFragmentPadding/*top*//*+theTextView.textContainer.lineFragmentPadding*//*there is no bottom padding*/));

    CGSize calculatedSize = [theTextView.text sizeWithFont:theTextView.font
                                          constrainedToSize:textViewContentSize
                                              lineBreakMode:NSLineBreakByWordWrapping];


    CGSize adjustedSize = CGSizeMake(ceilf(calculatedSize.width), ceilf(calculatedSize.height));
1 голос
/ 22 декабря 2012

Лучшее решение, которое я нашел до сих пор, - это иметь отдельный скрытый UITextView с теми же настройками шрифта и установить его текст. После этого его contexttize должен быть точным.

1 голос
/ 25 февраля 2010

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

0 голосов
/ 14 марта 2013

Вдохновленный ответом @ MrNickBarker, вот мое решение:

CGFloat width = 280.0f;

UITextView *t = [[UITextView alloc] init];
[t setFont:[UIFont systemFontOfSize:17]];
[label setText:@"some short or long text, works both"];

CGRect frame = CGRectMake(0, 0, width, 0);
[t setFrame:frame];
// Here's the trick: after applying the 0-frame, the content size is calculated and can be used in a second invocation
frame = CGRectMake(0, 0, width, t.contentSize.height);
[t setFrame:frame];

Единственная проблема, которая остается для меня, заключается в том, что это не работает с модифицированными вставками.

До сих пор не могу поверить, что такие повороты требуются, но поскольку -[NSString sizeWithFont:forWidth:lineBreakMode:] не учитывает вставки, отступы, поля, межстрочные интервалы и т. П., Похоже, это единственное работающее решение на данный момент (то есть iOS 6).

...