Изменение размера настраиваемой высоты UITableViewCell и высоты UITextView в этой ячейке (при наличии других элементов пользовательского интерфейса)

У меня есть настраиваемая ячейка таблицы, содержащая 3 метки, кнопку и UITextView.

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

Я пытаюсь установить правильную высоту как для UITextView, так и для пользовательской ячейки таблицы на основе текста, который я ввел в UITextView.

Текст для UITextView устанавливается в методе - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath.

Здесь я пытаюсь изменить размер UITextView (bodyTextView), используя следующее:

CGSize stringSize = [cell.bodyTextView.text sizeWithFont:cell.bodyTextView.font constrainedToSize:CGSizeMake(cell.bodyTextView.bounds.size.width, 9999) lineBreakMode:NSLineBreakByWordWrapping];

[cell.bodyTextView setText:threadMessage.body];

CGRect bodyFrame = cell.bodyTextView.frame;

bodyFrame.size = cell.bodyTextView.contentSize;

[cell.bodyTextView setFrame:bodyFrame];

Кажется, что это более или менее работает нормально, либо мой UIButton не перемещается туда, где должен, даже несмотря на то, что у него есть ограничение «Top Space To» в нижней части моего UITextView. Я бы подумал, что он автоматически переместится. Однако я могу переместить это в соответствующее место программно, так что не имеет большого значения.

Следующий фрагмент кода устанавливает размер tableViewCell до соответствующей высоты, чтобы поместиться в метки и UITextView, но для кнопки внизу недостаточно места. Затем я вычисляю высоту ячейки и возвращаю ее, используя следующее ...

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
    CGSize stringSize = [threadMessage.body sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(280, 9999) lineBreakMode:NSLineBreakByWordWrapping];

    float oldHeight = 28;
    float newHeight = stringSize.height;

    return tableView.rowHeight - oldHeight + newHeight;
}

Как видите, я делаю разницу в высоте между высотой UITextView и новой. Я попытался получить oldHeight программно, но получал сумасшедшие значения, исчисляемые многими тысячами.

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

Я чувствую, что у меня что-то происходит с курицей или яйцом, и я не могу понять это.

Я надеюсь разобраться с двумя основными проблемами:

1) Как правильно настроить размер UITextView с самого начала и сохранить его независимо от прокрутки экрана и выключения?

2) Как изменить размер моего настраиваемого TableCellView, чтобы включить высоту кнопки?

Я надеюсь, что все это имеет смысл, и я предоставил достаточно подробностей. Сообщите мне о любых вопросах.

Любые предложения будут очень признательны. Спасибо!

С уважением,

Питер


person Etep    schedule 23.11.2012    source источник


Ответы (3)


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

Я подумал, что проблема может быть связана с моим проектом, использующим iOS 6 SDK. Я загрузил симулятор iOS 5 и попытался запустить на нем свое приложение. У меня сразу после запуска возникла ошибка. NSLayoutInconsitencyException (или что-то подобное). После некоторого поиска в Интернете я обнаружил, что iOS 5 несовместима с настройками iOS 6.

Это был параметр «Автопрокладка пользователя», и он проверялся в моем файле раскадровки. Чтобы найти его, выберите файл раскадровки, а затем выберите File Inspector справа (Command-Option-1). Под разделом документа Interface Builder вы увидите флажок «Использовать автоматическое размещение». Снимите этот флажок, и все стало работать намного лучше. Размер моего UITextView больше не изменялся до одной строки и обратно до полной длины каждый раз, когда я прокручивал ячейку на экране и за его пределами.

Однако у меня все еще была проблема с ячейкой не совсем правильной высоты. Это оказалось очень просто теперь, когда я прояснил проблему Autolayout (вы не поверите, весь закомментированный тестовый код проб и ошибок, который у меня был повсюду :)).

В функции cellforRowAtIndexPath вам нужно установить текст UITextView таким, каким вы хотите, а затем просто получить его contentSize, а затем изменить размер фрейма вашего UITextView ...

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCellIdentifier"];

    [cell.bodyTextView setText:myText];

    CGRect bodyFrame = cell.bodyTextView.frame;
    bodyFrame.size = cell.bodyTextView.contentSize;
    [cell.bodyTextView setFrame:bodyFrame];

    ... Whatever else you need to do here ...
}

Затем в heightForRowAtIndexPath я обнаружил, что, снова получив ячейку и установив текст, я смог получить правильную разницу в размере и, следовательно, вернуть правильный размер. Используя разницу в размерах, он позволяет использовать любые другие элементы пользовательского интерфейса, которые могут быть в ячейке таблицы.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCellIdentifier"]; 

    float oldHeight = cell.bodyTextView.frame.size.height;

    cell.bodyTextView.text = threadMessage.body;

    CGRect bodyFrame = cell.bodyTextView.frame;
    bodyFrame.size = cell.bodyTextView.contentSize;

    float newHeight = cell.bodyTextView.contentSize.height;

    return tableView.rowHeight - oldHeight + newHeight;
}

Надеюсь, это кому-то поможет в будущем. Не стесняйтесь задавать мне любые вопросы, если что-то из этого не имело смысла. Спасибо Мохиту за попытку помочь мне. Очень признателен.

person Etep    schedule 23.11.2012

Etep, просто попробуйте это ... прежде всего вы отключите свойство изменения размера / ориентации ячейки и кнопки, а затем, когда вы можете сделать правильный размер текстового представления в соответствии с вашим поступающим текстом, чтобы вы вычисляли высота строки, вместо использования получения размера текста, то, что вам нужно, чтобы получить правильную высоту вашего текстового представления ... и все остальное в порядке. (в 'cellForRowAtIndexPath' вы должны использовать повторно используемую ячейку или сказать, поместите свой код внутри if (cell == nil) {})

person Mohit_Jaiswal    schedule 23.11.2012
comment
Спасибо за ответ Мохит! Я использую dequeueReusableCellWithIdentifier для повторного использования ячеек, просто не поместил это в приведенный выше код. :) В остальном, признаюсь, я не уверен, что понимаю? Я не уверен, что вы имеете в виду под свойством изменения размера / ориентации ячейки и кнопки? Вы имели в виду выключить? Как? Также вы упомянули, что вместо получения размера текста (это единственное, что работает правильно) я должен получить высоту textView? Я предполагаю, что использую frame.size.height? Я пробовал это, но текст еще не записан в текстовое представление, поскольку heightForRoawAtIndexPath вызывается до cellForRowAtIndexPath. - person Etep; 23.11.2012
comment
Поскольку я обнаружил, что ваша кнопка находится в неправильном положении для этого, единственное, что может произойти, если ваша ячейка автоматически изменит размер вложенных представлений, поэтому просто снимите отметку с этого свойства в IB, а также проверьте параметр окна, в котором будет виден ваш компонент, и, самое главное, Важно то, что высота вашей строки должна изменяться в соответствии с текстовым представлением, а не с тем, которое вы использовали, поскольку они никогда не были равны. Кроме того, вы можете узнать, когда ваше текстовое поле заполнено вашими данными, и после этого просто явно вызвать heightForRowAtIndexPath. - person Mohit_Jaiswal; 23.11.2012
comment
Можете ли вы предоставить мне URL-адрес, с которого вы получаете данные, чтобы я мог сделать образец и сообщить вам соответственно :) - person Mohit_Jaiswal; 23.11.2012
comment
Я только что протестировал с некоторыми поддельными данными, и то, что я сделал сначала, я предположил, что мой размер textView до некоторого максимального предела, скажем, половина экрана и запустил процесс, и когда моя загрузка завершилась, я проверил эти данные из массива и после этого перезагрузил таблицу с правильным расчет ... - person Mohit_Jaiswal; 23.11.2012
comment
Что ж, я понял главную проблему. Я использовал iOS 6 SDK, и в раскадровке был установлен флажок Use Autolayout. Я снял этот флажок (а также перешел в Simulator 5.0), и это устранило проблему с изменением размеров UITextView при прокрутке табличного представления. Теперь мне просто нужно выбрать правильную высоту строки. Высота немного меньше, если это небольшой объем данных, но она увеличивается по мере увеличения количества текста. Мой код выше сокращает высоту строки, чем больше текста в текстовом представлении. - person Etep; 23.11.2012
comment
Мохит, не могли бы вы опубликовать образец кода на pastie.org и разместить здесь URL-адрес? - person Etep; 23.11.2012
comment
Ура, вы разбираетесь :) И это то же самое, что я предлагаю вам, упоминая ориентацию (поскольку просто пропущено собственное имя) ... Извините, не могу опубликовать сейчас, но сделаю через некоторое время ... :) - person Mohit_Jaiswal; 23.11.2012
comment
Рад, что вы разобрались, а также, если вам нужно найти этот URL pastie.org/5422536, но это только в целях тестирования на данный момент я не думаю об оптимизации. - person Mohit_Jaiswal; 23.11.2012

Я также столкнулся с этой же проблемой при автоматическом изменении размера пользовательских ячеек при вращении. После боя я получил решение авторизовать cell.contentView, потому что я добавляю свои представления как subview в cell.contentview.

Я использовал следующий код, и мой код работает нормально :)

cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
person Kirti Nikam    schedule 02.07.2013