Пользовательская настройка высоты ячейки ячейки в раскадровке не отвечает

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

Если я изменил "размер строки" в представлении таблицы, размер всех ячеек изменится. Я не хочу этого делать, так как я хочу нестандартный размер только для одной ячейки. Я видел много сообщений, у которых есть программное решение проблемы, но я бы предпочел сделать это через раскадровку, если это возможно.

Ответ 1

В динамических ячейках, rowHeight, установленном в UITableView, всегда переопределяет значение rowHeight отдельных ячеек.

Но в статических ячейках, rowHeight, установленных на отдельных ячейках, может переопределять UITableView.

Не уверен, что это ошибка, Apple может намеренно сделать это?

Ответ 2

Если вы используете UITableViewController, выполните этот метод:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

В функции строки вы можете выбрать "Высота". Например,

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == 0) {
       return 100;
    } 
    else {
       return 60;
    }
}

В этом примере высота первой строки составляет 100 пикселей, а остальные - 60 пикселей.

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

Ответ 3

Для динамических ячеек rowHeight, установленных в UITableView, всегда переопределяет отдельные ячейки rowHeight.

Это поведение, IMO, ошибка. Каждый раз, когда вы должны управлять своим пользовательским интерфейсом в двух местах, он подвержен ошибкам. Например, если вы измените размер своей ячейки в раскадровке, вы должны помнить об их изменении в heightForRowAtIndexPath:. Пока Apple не исправляет ошибку, лучшим решением проблемы является переопределить heightForRowAtIndexPath:, но использовать фактические ячейки прототипа из раскадровки, чтобы определить высоту, а не использовать магические числа. Вот пример:

- (CGFloat)tableView:(UITableView *)tableView 
           heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    /* In this example, there is a different cell for
       the top, middle and bottom rows of the tableView.
       Each type of cell has a different height.
       self.model contains the data for the tableview 
    */
    static NSString *CellIdentifier;
    if (indexPath.row == 0) 
        CellIdentifier = @"CellTop";
    else if (indexPath.row + 1 == [self.model count] )
        CellIdentifier = @"CellBottom";
    else
        CellIdentifier = @"CellMiddle";

    UITableViewCell *cell = 
              [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    return cell.bounds.size.height;
}

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

Ответ 4

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

Этот код:

  • Не требует, чтобы высота ячейки была установлена ​​в любом месте, кроме очевидного места в раскадровке.
  • Сохраняет высоту по причинам производительности.
  • Использует общую функцию для получения идентификатора ячейки для пути указателя, чтобы избежать дублирования логики

Благодаря Answerbot, Brennan и lensovet.

- (NSString *)cellIdentifierForIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = nil;

    switch (indexPath.section)
    {
        case 0:
            cellIdentifier = @"ArtworkCell";
            break;
         <... and so on ...>
    }

    return cellIdentifier;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];
    static NSMutableDictionary *heightCache;
    if (!heightCache)
        heightCache = [[NSMutableDictionary alloc] init];
    NSNumber *cachedHeight = heightCache[cellIdentifier];
    if (cachedHeight)
        return cachedHeight.floatValue;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    CGFloat height = cell.bounds.size.height;
    heightCache[cellIdentifier] = @(height);
    return height;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier = [self cellIdentifierForIndexPath:indexPath];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    <... configure cell as usual...>

Ответ 5

На самом деле есть два места, где вам нужно изменить высоту строки, сначала ячейку (вы уже это изменили) и теперь выберите "Вид таблицы" и проверьте "Инспектор размеров"

Ответ 6

Я думаю, что это ошибка.

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

Я решил эту проблему с помощью этого метода.

Ответ 7

Если вы используете быстрый, используйте это. Не используйте раскадровку, чтобы выбрать высоту строки. Программно задайте высоту таблицы строк следующим образом:

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if indexPath.row == 0 || indexPath.row == 1{
        let cell = self.tableView.dequeueReusableCellWithIdentifier("section1", forIndexPath: indexPath) as! Section1TableViewCell
        self.tableView.rowHeight = 150
        cell.label1.text = "hiiiiii"
        cell.label2.text = "Huiiilllllll"
        return cell

    } else {

        let cell = self.tableView.dequeueReusableCellWithIdentifier("section2", forIndexPath: indexPath) as! Section2TableViewCell
        self.tableView.rowHeight = 60
        cell.label3.text = "llll"
        return cell
    }

}

Ответ 8

Откройте раскадровку в представлении XML и попробуйте отредактировать атрибут rowHeight искомого элемента.

Это сработало для меня, когда я попытался установить custom rowHeight для моей прототипированной строки. Он не работает через инспектора, но через XML он работает.

Ответ 9

Вы можете получить высоту UITableviewCell (в UITableviewController - статические ячейки) из раскадровки с помощью следующих строк.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
   CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath];

    return height;
}

Ответ 10

Вы можете использовать прототип cells с пользовательским height, а затем вызвать cellForRowAtIndexPath: и вернуть его frame.height.:.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self tableView:tableView
                    cellForRowAtIndexPath:indexPath];
    return cell.frame.size.height;
}

Ответ 11

Если вы хотите установить статическую высоту строки, вы можете сделать что-то вроде этого:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 120;
}

Ответ 12

Недавно я боролся с этим. Моя проблема заключалась в том, что решения, описанные выше, используя метод heightForRowAtIndexPath:, будут работать для iOS 7.1 в симуляторе, но затем полностью перевернут результаты, просто переключившись на iOS 8.1.

Я начал больше читать о ячейках для самостоятельной калибровки (представлен в iOS 8, читайте здесь). Было очевидно, что использование UITableViewAutomaticDimension поможет в iOS 8. Я попытался использовать эту технику и удалил использование heightForRowAtIndexPath: и voila, теперь он отлично работает в iOS 8. Но тогда iOS 7 не было. Что мне делать? Мне нужен heightForRowAtIndexPath: для iOS 7, а не для iOS 8.

Вот мое решение (подрезанное ради краткости), которое заимствует из ответа @JosephH, вышедшего выше:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tableView.estimatedRowHeight = 50.;
    self.tableView.rowHeight = UITableViewAutomaticDimension;

    // ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        return UITableViewAutomaticDimension;

    } else {
        NSString *cellIdentifier = [self reuseIdentifierForCellAtIndexPath:indexPath];
        static NSMutableDictionary *heightCache;
        if (!heightCache)
            heightCache = [[NSMutableDictionary alloc] init];
        NSNumber *cachedHeight = heightCache[cellIdentifier];
        if (cachedHeight)
            return cachedHeight.floatValue;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    CGFloat height = cell.bounds.size.height;
    heightCache[cellIdentifier] = @(height);
    return height;
    }
}

- (NSString *)reuseIdentifierForCellAtIndexPath:(NSIndexPath *)indexPath {
    NSString * reuseIdentifier;
    switch (indexPath.row) {
        case 0:
            reuseIdentifier = EventTitleCellIdentifier;
            break;
        case 2:
            reuseIdentifier = EventDateTimeCellIdentifier;
            break;
        case 4:
            reuseIdentifier = EventContactsCellIdentifier;
            break;
        case 6:
            reuseIdentifier = EventLocationCellIdentifier;
            break;
        case 8:
            reuseIdentifier = NotesCellIdentifier;
            break;
        default:
            reuseIdentifier = SeparatorCellIdentifier;
            break;
    }

    return reuseIdentifier;
}

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO (@ "8.0" ) на самом деле из набора макроопределений, которые я использую, которые я нашел где-то (очень полезно). Они определяются как:

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

Ответ 13

Для динамических ячеек rowHeight, установленный в UITableView, всегда переопределяет значение rowHeight отдельных ячеек. Просто вычислите динамическую высоту, если содержимое внутри строки.

Ответ 14

Единственное реальное решение, которое я смог найти, - это

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = ...; // Instantiate with a "common" method you'll use again in cellForRowAtIndexPath:
    return cell.frame.size.height;
}

Это работает и позволяет не иметь ужасного переключателя/если дублировать логику уже в StoryBoard. Не уверен в производительности, но я предполагаю, что при приходе в cellForRow: ячейка уже инициализируется так же быстро. Конечно, здесь, вероятно, есть побочные убытки, но похоже, что это отлично работает для меня здесь.

Я также разместил это здесь: https://devforums.apple.com/message/772464

EDIT: Ortwin Gentz ​​ напомнил мне, что heightForRowAtIndexPath: будет вызываться для всех ячеек TableView, а не только видимые. Звучит логично, так как iOS должна знать общую высоту, чтобы иметь возможность показывать правые полосы прокрутки. Это означает, что он, вероятно, отлично подходит для небольших TableViews (например, 20 ячеек), но забыл об этом на 1000 Cell TableView.

Кроме того, предыдущий трюк с XML: То же, что и первый комментарий для меня. Правильное значение уже было.

Ответ 15

Добавлен как комментарий, но публикуется как ответ для видимости:

Похоже, что проблема возникает, если вы сначала настроили представление таблицы как "статические ячейки", а затем изменили ее на "динамические прототипы". У меня возникла проблема, когда игнорировался даже метод делегата для heightForRowAtIndexPath. Сначала я разрешил его, непосредственно отредактировав XML-версию раскадровки, а затем, наконец, просто перестроил сцену раскадровки с нуля, используя динамические прототипы с самого начала.

Ответ 16

Учитывая, что я не нашел решения этой проблемы через Interface Builder, я решил опубликовать программное решение проблемы в Swift, используя две динамические ячейки, даже хотя первоначальный вопрос потребовал разрешения через Interface Builder. Несмотря на это, я думаю, что это может быть полезно для сообщества:

    import UIKit

    enum SignInUpMenuTableViewControllerCellIdentifier: String {
       case BigButtonCell = "BigButtonCell"
       case LabelCell = "LabelCell"
    }

    class SignInUpMenuTableViewController: UITableViewController {
            let heightCache = [SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell : CGFloat(50),
                              SignInUpMenuTableViewControllerCellIdentifier.LabelCell : CGFloat(115)]

    private func cellIdentifierForIndexPath(indexPath: NSIndexPath) -> SignInUpMenuTableViewControllerCellIdentifier {
        if indexPath.row == 2 {
            return SignInUpMenuTableViewControllerCellIdentifier.LabelCell
        } else {
            return SignInUpMenuTableViewControllerCellIdentifier.BigButtonCell
        }
    }

   override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
       return self.heightCache[self.cellIdentifierForIndexPath(indexPath)]!
   }

   ...

  }

Ответ 17

Еще одна вещь, которую вы можете сделать, - это перейти к своей структуре документа, выбрать представление таблицы, в котором ваша ячейка прототипа является вложенной. Затем в "Инспекторе размеров" измените таблицу "Высота таблицы" на нужное значение и снимите флажок "Автоматически".

Ответ 18

Та же проблема возникла при работе с XCode 9 с помощью Swift 4.

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