Вопрос:

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

ios cocoa-touch autolayout uikit uitextview

361581 просмотра

30 ответа

6362 Репутация автора

Есть ли хороший способ настроить размер, UITextViewчтобы соответствовать его содержанию? Скажем, например, у меня есть, UITextViewкоторый содержит одну строку текста:

"Hello world"

Затем я добавляю еще одну строку текста:

"Goodbye world"

Есть ли хороший способ в Cocoa Touch, чтобы получить тот, rectкоторый будет содержать все строки в текстовом представлении, чтобы я мог соответствующим образом настроить родительский вид?

В качестве другого примера посмотрите на поле заметок для событий в приложении «Календарь» - обратите внимание, как ячейка (и UITextViewсодержащаяся в ней) расширяется, чтобы вместить все строки текста в строке заметок.

Автор: drewh Источник Размещён: 08.09.2008 07:21

Ответы (30)


12 плюса

5968 Репутация автора

Ты пробовал [textView sizeThatFits:textView.bounds]?

Редактировать: sizeThatFits возвращает размер, но фактически не изменяет размер компонента. Я не уверен, что это то, что вы хотите, или если [textView sizeToFit]это больше, что вы искали. В любом случае, я не знаю, будет ли он идеально соответствовать контенту, который вы хотите, но это первое, что нужно попробовать.

Автор: Mike McMaster Размещён: 08.09.2008 08:36

9 плюса

146 Репутация автора

Другой метод является найти размер конкретной строки будет занимать с помощью NSStringметода:

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

Это возвращает размер прямоугольника, который соответствует данной строке с данным шрифтом. Передайте размер с желаемой шириной и максимальной высотой, а затем вы можете посмотреть на высоту, возвращаемую в соответствии с текстом. Существует версия, которая позволяет также указать режим разрыва строки.

Затем вы можете использовать возвращенный размер, чтобы изменить размер вашего представления, чтобы соответствовать.

Автор: Code Addict Размещён: 20.09.2008 06:19

6 плюса

18637 Репутация автора

В сочетании с ответом Майка МакМастера вы можете сделать что-то вроде:

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}
Автор: Olie Размещён: 06.11.2008 04:31

24 плюса

251 Репутация автора

По моему (ограниченному) опыту,

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

не учитывает символы новой строки, поэтому вы можете получить намного короче, CGSizeчем требуется на самом деле.

- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

похоже, уважает новые строки.

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

Автор: user63934 Размещён: 08.02.2009 07:01

1 плюс

27 Репутация автора

Надеюсь это поможет:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}
Автор: Dr. Marty Размещён: 17.03.2010 05:31

576 плюса

14747 Репутация автора

Это больше не работает на iOS 7 или выше

На самом деле существует очень простой способ изменить размер UITextViewсодержимого до его правильной высоты. Это можно сделать с помощью UITextView contentSize.

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

Единственное , что следует отметить, что правильный contentSizeдоступен только послеUITextView того, как была добавлена к просмотру с addSubview. До этого он равенframe.size

Это не будет работать, если включена автоматическая разметка. При автоматической компоновке общий подход заключается в использовании sizeThatFitsметода и обновлении constantзначения ограничения высоты.

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraint это ограничение макета, которое вы обычно устанавливаете с помощью IBOutlet, связывая свойство с ограничением высоты, созданным в раскадровке.


Просто добавьте к этому удивительному ответу 2014, если вы:

[self.textView sizeToFit];

есть разница в поведении только с iPhone6 ​​+ :

введите описание изображения здесь

Только с 6+ (не с 5 или 6) он добавляет «еще одну пустую строку» в UITextView. «Решение RL» прекрасно это исправляет:

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

Исправляет проблему «лишней линии» на 6+.

Автор: Ronnie Liew Размещён: 21.03.2010 02:26

6 плюса

71 Репутация автора

Я нашел способ изменить высоту текстового поля в соответствии с текстом внутри него, а также расположить метку под ним в зависимости от высоты текстового поля! Вот код

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;

[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];
Автор: dheeraj Размещён: 14.03.2011 10:13

1 плюс

631 Репутация автора

если кто-нибудь еще доберется до меня, это решение подойдет мне, 1 «Ронни Лью» +4 «user63934» (мой текст приходит из веб-службы): обратите внимание на 1000 (ничто не может быть таким большим «в моем случае»)

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];

NSString *dealDescription = [client objectForKey:@"description"];

//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];

CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);

UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];

dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];

//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

И это ... Ура

Автор: Alejo JM Размещён: 30.07.2012 01:56

4 плюса

572 Репутация автора

Это хорошо работало, когда мне нужно было сделать текст UITextViewвписывающимся в определенную область:

// Текст должен быть уже добавлен в подпредставление, иначе размер содержимого будет неправильным.

- (void) reduFontToFit: (UITextView *) tv {
    UIFont * font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height> tv.frame.size.height && pointSize> 7.0) {
        pointSize - = 1,0;
        UIFont * newFont = [UIFont fontWithName: font.fontName size: pointSize];
        tv.font = newFont;
    }
    if (pointSize! = font.pointSize)
        NSLog (@ "шрифт до% .1f от% .1f", pointSize, tv.font.pointSize);
}
Автор: Bill Cheswick Размещён: 08.10.2012 05:59

8 плюса

13986 Репутация автора

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

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;

CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

Здесь каждая 8 учитывает один из четырех заполненных краев, а 100000 служит очень большим максимальным размером.

На практике вы можете добавить дополнительный font.leadingк высоте; это добавляет пустую строку ниже вашего текста, которая может выглядеть лучше, если есть визуально тяжелые элементы управления непосредственно под текстовым представлением.

Автор: Brent Royal-Gordon Размещён: 24.10.2012 11:20

1 плюс

3953 Репутация автора

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

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

или вы можете использовать

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];
Автор: Manju Размещён: 06.09.2013 06:27

22 плюса

15085 Репутация автора

В iOS6 вы можете проверить contentSizeсвойство UITextView сразу после установки текста. В iOS7 это больше не будет работать. Если вы хотите восстановить это поведение для iOS7, поместите следующий код в подкласс UITextView.

- (void)setText:(NSString *)text
{
    [super setText:text];

    if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) {
        CGRect rect = [self.textContainer.layoutManager usedRectForTextContainer:self.textContainer];
        UIEdgeInsets inset = self.textContainerInset;
        self.contentSize = UIEdgeInsetsInsetRect(rect, inset).size;
    }
}
Автор: phatmann Размещён: 16.09.2013 09:35

3 плюса

3010 Репутация автора

Для iOS 7.0 вместо установки frame.size.heightна contentSize.height(который в настоящее время ничего не делает) использовать [textView sizeToFit].

Смотрите этот вопрос .

Автор: Stian Høiland Размещён: 20.09.2013 02:39

599 плюса

6899 Репутация автора

Решение

Это работает как для iOS 6.1, так и для iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    textView.frame = newFrame;
}

Или в Swift (Работает с Swift 4.1 в iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

Если вам нужна поддержка iOS 6.1, вам также следует:

textview.scrollEnabled = NO;
Автор: jhibberd Размещён: 21.09.2013 10:26

18 плюса

3688 Репутация автора

Я опубликую правильное решение в нижней части страницы на тот случай, если кто-то проявит смелость (или достаточно отчаялся), чтобы прочитать эту статью.

Вот репозиторий gitHub для тех, кто не хочет читать весь этот текст: resizableTextView

Это работает с iOs7 (и я верю, что это будет работать с iOs8) и с autolayout. Вам не нужны магические числа, отключить макет и тому подобное. Краткое и элегантное решение.

Я думаю, что весь код, связанный с ограничениями, должен идти в updateConstraintsметод. Итак, давайте сделаем наши собственные ResizableTextView.

Первая проблема, с которой мы здесь сталкиваемся, заключается в том, что мы не знаем реальный размер контента перед viewDidLoadметодом. Мы можем взять длинный и ошибочный путь и рассчитать его на основе размера шрифта, разрывов строк и т. Д. Но нам нужно надежное решение, поэтому мы сделаем:

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

Так что теперь мы знаем реальный размер контента независимо от того, где мы находимся: до или после viewDidLoad. Теперь добавьте ограничение высоты для textView (через раскадровку или код, независимо от того, как). Мы скорректируем это значение с помощью нашего contentSize.height:

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

Последнее, что нужно сделать, это сказать суперклассу updateConstraints.

[super updateConstraints];

Теперь наш класс выглядит так:

ResizableTextView.m

- (void) updateConstraints {
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

Красиво и чисто, правда? И вам не нужно иметь дело с этим кодом в ваших контроллерах !

Но ждать! У НЕТ АНИМАЦИИ!

Вы можете легко анимировать изменения, чтобы textViewплавно растягиваться. Вот пример:

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
Автор: Nikita Took Размещён: 25.07.2014 07:32

90 плюса

2357 Репутация автора

Для динамического определения размера UITextViewвнутри UITableViewCellя обнаружил, что следующая комбинация работает в Xcode 6 с iOS 8 SDK:

  • Добавьте UITextViewк a UITableViewCellи ограничьте его по сторонам
  • Установите для свойства UITextView' . При включенной прокрутке кадр не зависит от размера его содержимого, но при отключенной прокрутке между ними существует связь.scrollEnabledNOUITextView
  • Если ваша таблица использует исходную высоту строки по умолчанию, равную 44, тогда она автоматически вычислит высоту строки, но если вы изменили высоту строки по умолчанию на что-то другое, вам может потребоваться вручную включить автоматический расчет высоты строки в viewDidLoad:

    tableView.estimatedRowHeight = 150;
    tableView.rowHeight = UITableViewAutomaticDimension;
    

Для динамического определения размера только для чтения UITextView, вот и все. Если вы разрешаете пользователям редактировать текст в вашем UITextView, вам также необходимо:

  • Реализуйте textViewDidChange:метод UITextViewDelegateпротокола и попросите tableViewперерисовывать себя каждый раз, когда текст редактируется:

    - (void)textViewDidChange:(UITextView *)textView;
    {
        [tableView beginUpdates];
        [tableView endUpdates];
    }
    
  • И не забудьте установить UITextViewделегата где-нибудь, в Storyboardили вtableView:cellForRowAtIndexPath:

Автор: Brett Donald Размещён: 28.10.2014 01:12

1 плюс

1805 Репутация автора

Для тех, кто хочет, чтобы текстовый вид действительно двигался вверх и поддерживал позицию нижней строки

CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;

if(frame.size.height > textView.frame.size.height){
    CGFloat diff = frame.size.height - textView.frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y - diff, textView.frame.size.width, frame.size.height);
}
else if(frame.size.height < textView.frame.size.height){
    CGFloat diff = textView.frame.size.height - frame.size.height;
    textView.frame = CGRectMake(0, textView.frame.origin.y + diff, textView.frame.size.width, frame.size.height);
}
Автор: Gal Blank Размещён: 30.11.2014 09:43

6 плюса

461 Репутация автора

Ребята, использующие autolayout, и ваш sizetofit не работает, тогда, пожалуйста, проверьте ограничение ширины один раз. Если вы пропустили ограничение ширины, высота будет точной.

Нет необходимости использовать любой другой API. только одна строка решит все проблемы.

[_textView sizeToFit];

Здесь я интересовался только высотой, сохраняя фиксированную ширину и пропустив ограничение ширины моего TextView в раскадровке.

И это должно было показать динамический контент от сервисов.

Надеюсь, что это может помочь ..

Автор: Swaroop S Размещён: 02.01.2015 06:58

4 плюса

21991 Репутация автора

вот быстрая версия @jhibberd

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
    cell.msgText.text = self.items[indexPath.row]
    var fixedWidth:CGFloat = cell.msgText.frame.size.width
    var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
    var newSize:CGSize = cell.msgText.sizeThatFits(size)
    var newFrame:CGRect = cell.msgText.frame;
    newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
    cell.msgText.frame = newFrame
    cell.msgText.frame.size = newSize        
    return cell
Автор: Fareed Alnamrouti Размещён: 07.03.2015 04:02

1 плюс

428 Репутация автора

Единственный работающий код - это тот, который использует «SizeToFit», как в ответе jhibberd выше, но на самом деле он не подхватит, если вы не вызовете его в ViewDidAppear или не подключите его к событию изменения текста UITextView.

Автор: Mohammad Zekrallah Размещён: 08.04.2015 08:25

1 плюс

4790 Репутация автора

Основываясь на ответе Никиты Тука, я пришел к следующему решению в Swift, которое работает на iOS 8 с autolayout:

    descriptionTxt.scrollEnabled = false
    descriptionTxt.text = yourText

    var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
    for c in descriptionTxt.constraints() {
        if c.isKindOfClass(NSLayoutConstraint) {
            var constraint = c as! NSLayoutConstraint
            if constraint.firstAttribute == NSLayoutAttribute.Height {
                constraint.constant = contentSize.height
                break
            }
        }
    }
Автор: Apfelsaft Размещён: 13.05.2015 12:46

1 плюс

5340 Репутация автора

Быстрый ответ: следующий код вычисляет высоту вашего textView.

                let maximumLabelSize = CGSize(width: Double(textView.frame.size.width-100.0), height: DBL_MAX)
                let options = NSStringDrawingOptions.TruncatesLastVisibleLine | NSStringDrawingOptions.UsesLineFragmentOrigin
                let attribute = [NSFontAttributeName: textView.font!]
                let str = NSString(string: message)
                let labelBounds = str.boundingRectWithSize(maximumLabelSize,
                    options: NSStringDrawingOptions.UsesLineFragmentOrigin,
                    attributes: attribute,
                    context: nil)
                let myTextHeight = CGFloat(ceilf(Float(labelBounds.height)))

Теперь вы можете установить высоту вашего textView в myTextHeight

Автор: RawMean Размещён: 16.05.2015 11:16

6 плюса

1748 Репутация автора

Начиная с iOS 8, можно использовать функции автоматического макета UITableView для автоматического изменения размера UITextView без какого-либо пользовательского кода вообще. Я поместил проект в github, который демонстрирует это в действии, но вот ключ:

  1. У UITextView должна быть отключена прокрутка, которую вы можете сделать программно или через конструктор интерфейса. Размер не изменится, если включена прокрутка, потому что прокрутка позволяет просматривать содержимое большего размера.
  2. В viewDidLoad для UITableViewController вы должны установить значение дляtimateRowHeight, а затем установить rowHeightв UITableViewAutomaticDimension.

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.estimatedRowHeight = self.tableView.rowHeight;
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}
  1. Цель развертывания проекта должна быть iOS 8 или выше.
Автор: Chuck Krutsinger Размещён: 04.06.2015 05:41

58 плюса

4282 Репутация автора

Свифт:

textView.sizeToFit()
Автор: Juan Boero Размещён: 01.10.2015 06:32

7 плюса

36817 Репутация автора

Достаточно следующих вещей:

  1. Просто не забудьте установить для прокрутки значение NO для вашего UITextView:

введите описание изображения здесь

  1. Правильно установите ограничения Auto Layout.

Вы можете даже использовать UITableViewAutomaticDimension.

Автор: Bartłomiej Semańczyk Размещён: 02.11.2015 10:18

7 плюса

2259 Репутация автора

Мы можем сделать это с помощью ограничений.

  1. Установите ограничения высоты для UITextView. введите описание изображения здесь

2. Создайте IBOutlet для этого ограничения высоты.

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3. не забудьте установить делегат для вашего textview.

4.

-(void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

тогда обновите свое ограничение как это :)

Автор: Kishore Kumar Размещён: 04.03.2016 07:16

61 плюса

12663 Репутация автора

Очень простое рабочее решение с использованием кода и раскадровки.

По коду

textView.scrollEnabled = false

По раскадровке

Снимите флажок Включить прокрутку

введите описание изображения здесь

Не нужно ничего делать кроме этого.

Автор: Alok Размещён: 17.07.2016 07:06

4 плюса

1435 Репутация автора

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

поэтому при настройке текстового представления отключите прокрутку

textView.isScrollEnabled = false

и затем в методе делегата func textViewDidChange(_ textView: UITextView)добавьте этот код:

func textViewDidChange(_ textView: UITextView) {
    let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    textView.frame = CGRect(origin: textView.frame.origin, size: newSize)
}

Выходы:

введите описание изображения здесь

введите описание изображения здесь

Автор: Peter Stajger Размещён: 21.03.2017 01:38

1 плюс

116 Репутация автора

Вот ответ, если вам нужно изменить размер textViewи tableViewCellдинамически вstaticTableView

[ https://stackoverflow.com/a/43137182/5360675][1]

Автор: Volodymyr Nazarkevych Размещён: 31.03.2017 09:39

4 плюса

2304 Репутация автора

отключить прокрутку

добавить содержание

и добавьте свой текст

[yourTextView setText:@"your text"];
[yourTextView layoutIfNeeded];

если вы используете, UIScrollViewвы должны добавить это тоже;

[yourScrollView layoutIfNeeded];

-(void)viewDidAppear:(BOOL)animated{
    CGRect contentRect = CGRectZero;

    for (UIView *view in self.yourScrollView.subviews) {
         contentRect = CGRectUnion(contentRect, view.frame);
    }
    self.yourScrollView.contentSize = contentRect.size;
}
Автор: alicanozkara Размещён: 10.01.2018 01:06
Вопросы из категории :
32x32