Пользовательская настройка высоты строки ячейки в раскадровке не отвечает
Я пытаюсь настроить высоту ячейки для одной из ячеек в моем представлении таблицы. Я настраиваю размер из параметра " высота строки "внутри" инспектора размера " рассматриваемой ячейки. Когда я запускаю приложение на своем iPhone, ячейка имеет размер по умолчанию, установленный из "размера строки" в табличном представлении.
Если я изменю "размер строки" табличного представления, то размер всех ячеек изменится. Я не хочу этого делать, так как я хочу пользовательский размер только для одной ячейки. Я видел много сообщений, которые есть программное решение проблемы, но я бы предпочел сделать это через раскадровку, если это возможно.
18 ответов:
On динамический клетки,
rowHeightset на UITableView всегда переопределяет rowHeight отдельных ячеек.но на статический клетки,
rowHeightустановить на отдельных ячейках можно переопределить UITableView.Не уверен, что это ошибка, Apple, возможно, намеренно делает это?
Если вы используете 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 пикселей.
Я надеюсь, это может помочь вам.
для динамических ячеек,
rowHeightустановить наUITableViewвсегда переопределяет отдельные клетки'rowHeight.это поведение, ИМО, ошибка. В любое время, когда вам нужно управлять своим пользовательским интерфейсом в двух местах, он склонен к ошибке. Например, если вы измените размер ячейки в раскадровке, вы должны помнить, чтобы изменить их в
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; }это гарантирует, что любые изменения высоты ячейки прототипа будут автоматически подобраны во время выполнения, и вам нужно только управлять своим пользовательским интерфейсом в одном месте: раскадровка.
Я построил код, на который намекают различные ответы/комментарии, чтобы это работало для раскадровок, которые используют ячейки прототипа.
этот код:
- не требует, чтобы высота ячейки была установлена в любом месте, кроме очевидного места в раскадровке
- кэширует высоту по соображениям производительности
- использует общую функцию для получения идентификатора ячейки для пути индекса, чтобы избежать дублирования логики
спасибо Answerbot, Бреннан и Ленсовет.
- (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...>
на самом деле есть два места, где вам нужно изменить высоту строки, сначала ячейку (вы уже изменили это) а теперь выберите вид таблицы и проверьте размер инспектора
Я думаю, что это ошибка.
попробуйте настроить высоту не с помощью утилиты инспектора, а с помощью мыши перетащить на раскадровке непосредственно.
Я решил эту проблему с помощью этого метода.
Если вы используете 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 } }
откройте раскадровку в XML-представлении и попробуйте отредактировать
rowHeightатрибут нужного элемента.Он работал для меня, когда я пытался установить пользовательское значение rowheight на мой прототип подряд. Он не работает через инспектор, но через XML он работает.
вы можете получить высоту UITableviewCell (в UITableviewController - статические ячейки) из раскадровки с помощью следующих строк.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; return height; }
вы можете использовать прототип
cellsс пользовательскимheight, а затем вызватьcellForRowAtIndexPath:и вернуть егоframe.height.:.- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; return cell.frame.size.height; }
Если вы хотите установить статический высоту строки, вы можете сделать что-то вроде этого:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 120; }
Я недавно боролся с этим. Моя проблема заключалась в решениях, опубликованных выше с помощью
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)
для динамических ячеек rowHeight, установленный на UITableView, всегда переопределяет rowHeight отдельных ячеек. Просто вычислите динамическую высоту, если содержимое внутри строки.
такая же проблема возникла при работе над XCode 9 с помощью Swift 4.
Добавить Автомакет для элементов пользовательского интерфейса внутри ячейки и пользовательской высоты строки ячейки будет работать соответственно, как указано.
единственное реальное решение, которое я смог найти это
- (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; }это работает и позволяет не иметь ужасный переключатель/если дублирование логики уже в раскадровке. Не уверен в производительности, но я думаю, когда приеду в
cellForRow:ячейка уже инициализирована, это так же быстро. Конечно, есть, вероятно, сопутствующие убытки здесь, но похоже, что это отлично работает для меня здесь.Я также разместил это здесь: https://devforums.apple.com/message/772464
EDIT:Gentz Ортвин напомнил мне, что
heightForRowAtIndexPath:будет называться все ячейки TableView, а не только видимые. Звучит логично, так как iOS должна знать общую высоту, чтобы иметь возможность показывать правильные полосы прокрутки. Это означает, что это, вероятно, хорошо на небольших TableViews (например, 20 ячеек), но забудьте об этом на 1000 ячеек TableView.кроме того, предыдущий трюк с XML: то же самое, что первый комментарий для меня. Правильное значение уже было там.
добавлено в качестве комментария, но размещение в качестве ответа для видимости:
там, кажется, также есть проблема, если вы изначально установите табличное представление как "статические ячейки", а затем измените его на "динамические прототипы"."У меня была проблема, когда даже метод делегата для
heightForRowAtIndexPathбыл проигнорирован. Сначала я решил его путем прямого редактирования XML раскадровки, а затем, наконец, просто перестроил сцену раскадровки с нуля, используя динамические прототипы с самого начала.
учитывая, что я не нашел никакого решения этой проблемы через Interface Builder, я решил опубликовать программное решение проблемы в Свифт используя две динамические ячейки, даже если первоначальный вопрос задан для решения через 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)]! } ... }
еще одна вещь, которую вы можете сделать, это перейти к контуру документа, выберите табличное представление, в которое вложена ячейка прототипа. Затем в Инспекторе размеров измените высоту строки представления таблицы на нужное значение и снимите флажок Автоматически.
Comments