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


78

Я переношу один із додатків з iOS 6.1 на iOS 7. Я використовую макет, де є UITextViewширина виправлення, але її висота залежить від її розміру. Для iOS 6.1 було достатньо перевірити contentsize.height та встановити його як висоту кадру текстового перегляду, але він не працює на iOS 7.

Як я можу тоді створити UITextViewфіксовану ширину, але динамічну висоту на основі тексту, який він показує?

ПРИМІТКА. Я створюю ці подання з коду, а не за допомогою Interface Builder.

Відповіді:


180

За допомогою цього наступного коду ви можете змінити висоту вашого 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:)])‌

я можу дати вам це через 24 години. терпіть, це ваше :)
Золтан Вараді

16
Може, вам слід зробити посилання на відповіді, з яких ви їх взяли? stackoverflow.com/questions/18368567 / ...
андрей-Колфілд

@ Йорданія Монтел, з іншого питання, якщо я маю фіксовану ширину та висоту, як я можу знайти найкращий розмір шрифту для призначеного рядка? я маю подібну проблему на iOS7 (на iOS6 я можу це зробити)
LiangWang

1
@Jacky: спроби та помилки; збільшувати або зменшувати розмір на 1, поки його обчислена висота не буде занадто великою. Або зробіть його розміром 1000 і автоматично змініть розмір, щоб він підходив.
Cœur

ця відповідь ВЖЕ НЕПРАВИЛЬНА. Спробуйте ввести багато тексту всередину такого текстового поля. Раптом неправильний розмір? Принаймні NSStringDrawingUsesFontLeadingє зайвим
user2159978

42

Це працювало для мене для iOS6 та 7:

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

Привіт, так це для мене ... Я використовую "txtviewHeight.frame.size.height" замість "txtviewHeight.contentSize.height"
Мані

чому я отримую висоту властивості, яку не знайдено на об'єкті типу "UITextView"?
Hexark

@HexarktextView.bounds.size.height
користувач

21

У 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;

7
Ваша відповідь не відповідає питанню, але відповідає моїй проблемі. Тож я голосую :)
vietstone

Це не визначає розмір вмісту для мене. Прокрутка вимкнена.
Дволе

Цей фрагмент коду вирішив мою проблему, але що означає метод, що спричиняє покоління, для вашого коментаря?
Code Farmer

15

Використовуйте цю маленьку функцію

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

Працює в iOS6 та iOS7 для мене. Дякую!
Paul Brady

4

Моє остаточне рішення базується на 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

Є більш прості рішення, використовуючи цей метод:

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


Здається, ваше рішення не працює. Коли textview переходить до другого рядка usedRectForTextContainerметод повертає однакову висоту.
Валерій Павлов

О, може бути, я просто використовую його для відображення тексту
HotJard

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

Тільки не забувайте lineFragmentPadding


0

просте рішення - textView.isScrollEnabled = false ідеально працює, якщо всередині іншого подання прокрутки або комірки tableView зUITableViewAutomaticDimension


0

@ Ana's, @Blake Hamilton's рішення швидко .

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

Мені було добре, що це також повертає правильне значення contentSize, коли isScrollEnableвстановлено значення false. Якщо встановити значення false, повертається розмір кадру подання тексту замість розміру вмісту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.