it-swarm.com.ru

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

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

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

205
zirinisp

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

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

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

287
pixelfreak

Если вы используете 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 пикселей.

Я надеюсь, что этот может помочь вам.

82
Beber

Для динамических ячеек 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;
}

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

34
memmons

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

Этот код:

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

Спасибо Ответботу, Бреннану и Ленсовету.

- (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...>
22
JosephH

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

19
Kristjan H.

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

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

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

11
Fogni

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

 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
    }

}
9
Chathuranga Silva

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

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

6
Shtirlic

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

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

    return height;
}
6
Hiren Panchal

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

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

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

Я начал читать больше о самоконтролируемых ячейках (представлен в iOS 8, читайте здесь ). Было очевидно, что использование UITableViewAutomaticDimension поможет в iOS 8. Я попытался использовать эту технику и удалил использование heightForRowAtIndexPath: и вуаля, теперь она отлично работает в 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)
4
speby

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

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

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

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

1
Murari Varma

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

1
Aks

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

    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)]!
   }

   ...

  }
0
King-Wizard

Добавлен как комментарий, но размещен как ответ для наглядности: 

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

0
Eric Goldberg

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

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

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

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

0
StuFF mc

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

0
Amin Rezapour