IOS7 UITextView contentize.height альтернатива

Я переношу одно из приложений с iOS 6.1 на iOS 7. Я использую макет, где есть UITextView, который имеет ширину исправления, но высота основывается на его содержимом. Для iOS 6.1 проверка содержимого content.height и установка его в качестве высоты фрейма textview была достаточной, но она не работает на iOS 7.

Как я могу создать UITextView с фиксированной шириной, но динамическую высоту на основе отображаемого текста?

ПРИМЕЧАНИЕ. Я создаю эти представления из кода, а не с Interface Builder.

Ответ 1

С помощью этого следующего кода вы можете изменить высоту вашего UITextView в зависимости от фиксированной ширины (он работает на iOS 7 и предыдущей версии):

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
    UITextView *textView = [[UITextView alloc] init];
    [textView setAttributedText:text];
    CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

С помощью этой функции вы берете NSAttributedString и фиксированную ширину, чтобы вернуть требуемую высоту.

Если вы хотите рассчитать кадр из текста с определенным шрифтом, вам нужно использовать следующий код:

- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        CGRect frame = [text boundingRectWithSize:size
                                          options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                       attributes:@{NSFontAttributeName:font}
                                          context:nil];
        return frame.size;
    }
    else
    {
        return [text sizeWithFont:font constrainedToSize:size];
    }
}

Вы можете добавить, что SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO в файле prefix.pch в вашем проекте:

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Вы также можете заменить предыдущий тест SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) на:

if ([text respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)])‌

Ответ 2

Это работало для меня для iOS6 и 7:

CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
    self.myTextView.height = textViewSize.height;

Ответ 3

В iOS7, UITextView используется NSLayoutManager для текста макета:

// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions.  The default is NO.  Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked.  It also gives significant performance benefits, especially for large documents.
@property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;

отключить allowsNonContiguousLayout, чтобы исправить contentSize:

textView.layoutManager.allowsNonContiguousLayout = NO;

Ответ 4

Используйте эту небольшую функцию

-(CGSize) getContentSize:(UITextView*) myTextView{
    return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}

Ответ 5

Мое окончательное решение основано на HotJard, но включает верхнюю и нижнюю вставки текстового контейнера вместо использования 2 * fabs (textView.contentInset.top):

- (CGFloat)textViewHeight:(UITextView *)textView
{
    return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
                 textView.textContainerInset.top +
                 textView.textContainerInset.bottom);
}

Ответ 6

Более простое решение, используя этот метод:

+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
    if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
        textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
    }else{
        textView.height = textView.contentSize.height;
    }
}

UPD: работает только для отображения текста (isEditable = NO)

Ответ 7

   _textView.textContainerInset = UIEdgeInsetsZero;
   _textView.textContainer.lineFragmentPadding = 0;

Просто не забудьте строку FragmentPadding

Ответ 8

простое решение - textView.isScrollEnabled = false отлично работает, когда внутри другого вида прокрутки, или ячейки tableView с UITableViewAutomaticDimension