it-swarm.com.ru

iOS7 UITextView contentsize.height альтернатива

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

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

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

76
Zoltan Varadi

С помощью этого следующего кода вы можете изменить высоту вашего 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:)])‌
178
Jordan Montel

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

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

В 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;
20
nova

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

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

Мое окончательное решение основано на 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);
}
3
xZenon

Есть более простое решение, использующее этот метод: 

+(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)

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

Только не забудьте строку Фрагмент

1
ChaoWang

@ Ана, решение Блейка Гамильтона в Свифт

var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height

Хорошо для меня было то, что это также возвращает правильный contentSize, когда isScrollEnable установлен в false. Значение false вернуло размер кадра текстового представления вместо размера содержимого. 

0
Bem

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

0
Kirill Serebriakov