Инструменту UITableViewCell разверните на нажмите
Допустим, у нас есть пользовательский UITableViewCell
поэтому всякий раз, когда я нажимаю кнопку custom на ячейке.. он должен расширяться до некоторой степени (можно сказать, на 40 высоты больше...) и когда я снова нажимаю на ту же пользовательскую кнопку, она должна свернуться на предыдущую высоту.
разработчик, пожалуйста, направьте меня.. как я могу достичь этой задачи
9 ответов:
реализовать heightForRowAtIndexPath для расчета правильной высоты. Затем в коде для вашей кнопки заставьте таблицу переоценить высоту каждой ячейки с помощью beginUpdates plus endUpdates:
[self.tableView beginUpdates]; [self.tableView endUpdates];
изменения высоты ячеек tableview будут автоматически рассчитываться с помощью heightForRowAtIndexPath, и изменения также будут анимированы.
на самом деле, вместо кнопки на вашей ячейке, которая делает это, вы можете даже просто сделать выбор ячейки сделать это в
didSelectRowAtIndexPath
.
я не собираюсь здесь ничего говорить, чтобы противоречить принятому ответу, считая его совершенно правильным. Однако я собираюсь более подробно рассказать о том, как это сделать. Если вы не хотите читать все это и больше заинтересованы в игре с исходным кодом в рабочем проекте, я загрузил пример проекта на GitHub.
основная идея заключается в том, чтобы иметь состояние внутри метода
-tableView: heightForRowAtIndexPath:
это определяет, является ли текущая ячейка должна быть расширена. Это будет спровоцировано вызовом начала/окончания обновления на стол внутри-tableView: didSelectRowAtIndexPath:
в этом примере я покажу, как создать табличное представление, которое позволяет одновременно расширять одну ячейку.первое, что вам нужно сделать, это объявить ссылку на NSIndexPath
Я создал библиотеку с открытым исходным кодом для этого. Вы просто реализуете свернуть и развернуть делегаты в коде и вуаля! вы также можете выполнять любые рисунки и анимации. проверьте этой.
Я сделал многоразовый компонент, который будет делать именно то, о чем вы говорите. Это довольно простой в использовании, и есть демо-проект.
GCRetractableSectionController на GitHub.
вместо
[tableView beginUpdates]
и[tableView endUpdates]
, Я использую[tableView reloadRowsAtIndexPath:... withRowAnimation:...]
метод внутриdidSelectRowAtIndexPath
метод.Я предпочитаю это, потому что у меня были некоторые проблемы с элементами, которые должны показать, когда я расширяю свой
UITableViewCell
, когда я использовал методы begin & end updates. Другой момент заключается в том, что вы можете выбирать между некоторыми анимациями, такими как: сверху, снизу, слева, справа...
я использовал исходный код Gcamp и сделал свою версию.
1) в методе loadView инициализируйте изменяемый массив, в котором вы будете сохранять расширенные или нерасширенные состояния ваших разделов. Очень важно сохранить расширенные статусы в отдельном массиве, который не уничтожается при прокрутке табличного представления (например, если вы сохраняете его в headerView, он будет перерисован и забудет, что он был расширен или нет). В моем случае это массив _sectionStatuses.
- (void)loadView { // At the beginning all sections are expanded _sectionStates = [NSMutableArray arrayWithCapacity:self.tableView.numberOfSections]; for (int i = 0; i < self.tableView.numberOfSections; i++) { _sectionStates[i] = [NSNumber numberWithBool:YES]; } }
2) создать пользовательский headerView для раздела с кнопкой для расширения. Делегируйте действие от кнопки в вашем headerView к вашему TableViewController с помощью шаблона делегирования. Вы можете найти подходящие изображения в исходном коде Gcamp.
3) Создайте действие для удаления или добавления строк. Здесь _foldersArray-это моя структура, которая содержит все данные. HeaderView моего раздела-MCExpandableAccountHeaderView знает, что это собственный номер раздела - я передаю его туда, когда создаю представления заголовков для каждого раздела. Очень важно перенести его на этот метод, так как вы должны знать, какой раздел теперь расширен или растянут.
- (void)expandClicked:(MCAccountHeaderView *)sender { MCExpandableAccountHeaderView *expandableAccountHeaderView = (MCExpandableAccountHeaderView*)sender; // Finding a section, where a button was tapped NSInteger section = expandableAccountHeaderView.section; // Number of rows, that must be in a section when it is expanded NSUInteger contentCount = [_foldersArray[section - 1][@"folders"] count]; // Change a saved status of a section BOOL expanded = [_sectionStates[section] boolValue]; expanded = ! expanded; expandableAccountHeaderView.expanded = expanded; _sectionStates[section] = [NSNumber numberWithBool:expanded]; // Animation in a table [self.tableView beginUpdates]; NSMutableArray* modifiedIndexPaths = [[NSMutableArray alloc] init]; for (NSUInteger i = 0; i < contentCount; i++) { NSIndexPath* indexPath = [NSIndexPath indexPathForRow:i inSection:section]; [modifiedIndexPaths addObject:indexPath]; } if (expandableAccountHeaderView.expanded) [self.tableView insertRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade]; else [self.tableView deleteRowsAtIndexPaths:modifiedIndexPaths withRowAnimation:UITableViewRowAnimationFade]; [self.tableView endUpdates]; // Scroll to the top of current expanded section if (expandableAccountHeaderView.expanded) [self.tableView scrollToRowAtIndexPath:INDEX_PATH(0, section) atScrollPosition:UITableViewScrollPositionTop animated:YES]; }
4) также важно возвращать правильное число или строки в разделе в зависимости от погоды он расширяется или нет.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { BOOL expanded = [_sectionStates[section] boolValue]; return expanded ? [_foldersArray[section - 1][@"folders"] count] : 0; }
Это ответ Мика, но для Swift 4. (IndexPath заменяет NSIndexPath, который поставляется с пустым IndexPath, поскольку nil приведет к сбою Swift. Кроме того, вы можете сравнить два экземпляра IndexPath с помощью
==
)объявите свойство expandedIndexPath.
var expandedIndexPath = IndexPath()
дополнительная часть viewDidLoad.
expandedIndexPath = IndexPath(row: 1, section: 2)
затем часть didSelectRow.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.beginUpdates() if indexPath == expandedIndexPath { expandedIndexPath = IndexPath() } else { expandedIndexPath = indexPath } tableView.endUpdates() }
затем часть heightForRow.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath == expandedIndexPath { return 100 } return 44 }
initialize iSelectedIndex = -1; and declare UITableView *urTableView; - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 10; //Section count } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 3; //row count } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if(cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } [cell.textLabel setText:[NSString stringWithFormat:@"sec:%d,row:%d",indexPath.section,indexPath.row]]; return cell; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ // adding a label with the tap gesture to the header in each section headerLabel = [[UILabel alloc]init]; headerLabel.tag = section; headerLabel.userInteractionEnabled = YES; headerLabel.backgroundColor = [UIColor greenColor]; headerLabel.text = [NSString stringWithFormat:@"Header No.%d",section]; headerLabel.frame = CGRectMake(0, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height); UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(gestureTapped:)]; [headerLabel addGestureRecognizer:tapGesture]; return headerLabel; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 50.0; //adjust the height as you need } - (void)gestureTapped:(UITapGestureRecognizer *)sender{ UIView *theSuperview = self.view; // whatever view contains CGPoint touchPointInSuperview = [sender locationInView:theSuperview]; UIView *touchedView = [theSuperview hitTest:touchPointInSuperview withEvent:nil]; if([touchedView isKindOfClass:[UILabel class]]) { if (iSelectedIndex != touchedView.tag) { //if new header is selected , need to expand iSelectedIndex = touchedView.tag; }else{ // if the header is already expanded , need to collapse iSelectedIndex = -1; } [urTableView beginUpdates]; [urTableView endUpdates]; } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // Show or hide cell float height = 0.0; if (indexPath.section == iSelectedIndex) { height = 44.0; // Show the cell - adjust the height as you need } return height; }
добавить 0x7fffffff включительно по ответ, я обнаружил, что мне нужно дополнительное условие в операторе if внутри didSelectRowAtIndexPath - таким образом:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView beginUpdates]; if (self.expandedIndexPath && [indexPath compare:self.expandedIndexPath] == NSOrderedSame) { self.expandedIndexPath = nil; } else { self.expandedIndexPath = indexPath; } [tableView endUpdates]; }