Аккордеонная ячейка таблицы – Как динамически расширять / сокращать uitableviewcell?

Я пытаюсь создать аккордеонный тип uitableviewcell, который, когда пользователь выбирает ячейку, расширяется, чтобы отобразить подробный инфо-просмотр, похожий на то, как работает приложение digg. Сначала я попытался заменить текущую табличную ячейку на customcell в cellForRowAtIndex, однако анимация выглядит немного изменчивой, поскольку вы можете видеть заменяемую ячейку, и в целом эффект не работает.

Если вы посмотрите на приложение digg и другие, которые сделали это, кажется, что они arent заменяют текущую ячейку, но вместо этого, возможно, добавляют subview в ячейку? Оригинальная ячейка, однако, кажется, не анималирует вообще и только новые аккордеоны в таблице.

Есть ли у кого-нибудь идеи, как добиться подобного эффекта?

Обновление. Я сделал некоторый прогресс, используя метод neha ниже, и пока ячейка анимирует правильный путь, он разрушает хаос с другими ячейками в таблице. То, что я сделал, является подclassом UITableViewCell с пользовательским classом, который содержит экземпляр UIView, который на самом деле рисует представление, которое затем добавляю к содержимому содержимого ячеек таблицы.

- (void)setSelected:(BOOL)selected animated:(BOOL)animated { if (selected) { [self expandCell]; } } -(void)expandCell { self.contentView.frame = CGRectMake(0.0, 0.0, self.contentView.bounds.size.width, 110); } 

Вот все методы делегата таблицы, которые я использую:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (isSearching && indexPath.row == selectedIndex) { static NSString *CellIdentifier = @"SearchCell"; CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)]; theText.text = @"Title Text"; [cell.contentView addSubview:theText]; UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)]; textField.borderStyle = UITextBorderStyleLine; [cell.contentView addSubview:textField]; UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)]; testLabel.text = [NSString stringWithFormat:@"Some text here"]; [cell.contentView addSubview:testLabel]; [theText release]; [textField release]; [testLabel release]; return cell; } else { static NSString *CellIdentifier = @"Cell"; CustomTableCell *cell = (CustomTableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; selectedIndex = indexPath.row; isSearching = YES; [tableView beginUpdates]; [tableView endUpdates]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (isSearching && indexPath.row == selectedIndex) { return 110; } return rowHeight; } 

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

Есть идеи?

Способ Apple для Apple довольно прост.

Во-первых, вам нужно сохранить выбранную строку indexPath:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { self.selectedRowIndex = [indexPath retain]; [tableView beginUpdates]; [tableView endUpdates]; } 

Ниже я расскажу о начале и конце обновленной части.

Затем, когда у вас есть текущий выбранный индекс, вы можете сказать tableView, что он должен дать этой строке больше места.

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { //check if the index actually exists if(selectedRowIndex && indexPath.row == selectedRowIndex.row) { return 100; } return 44; } 

Это вернет высоту 100 для выбранной ячейки.

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

Надеюсь, это было полезно, Pawel

Pawel’s beginUpdates / endUpdates трюк хорош, и я часто его использую. Но в этом случае вам просто нужно перезагрузить строки, которые меняют состояние, гарантируя, что вы правильно перезагрузите их с помощью нужного типа ячейки и вернете правильную высоту новой ячейки.

Вот полная рабочая реализация того, что я думаю, что вы пытаетесь выполнить:

.час:

 #import  @interface ExpandingTableViewController : UITableViewController { } @property (retain) NSIndexPath* selectedIndexPath; @end 

.m:

 @implementation ExpandingTableViewController @synthesize selectedIndexPath; - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return 10; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier1 = @"Cell1"; static NSString *CellIdentifier2 = @"Cell2"; UITableViewCell *cell; NSIndexPath* indexPathSelected = self.selectedIndexPath; if ( nil == indexPathSelected || [indexPathSelected compare: indexPath] != NSOrderedSame ) { cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier1] autorelease]; } cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row]; } else { cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier2] autorelease]; } cell.textLabel.text = [NSString stringWithFormat: @"cell %d", indexPath.row]; cell.detailTextLabel.text = [NSString stringWithFormat: @"(expanded!)", indexPath.row]; } return cell; } #pragma mark - #pragma mark Table view delegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if ( self.selectedIndexPath != nil && [self.selectedIndexPath compare: indexPath] == NSOrderedSame ) { return tableView.rowHeight * 2; } return tableView.rowHeight; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSArray* toReload = [NSArray arrayWithObjects: indexPath, self.selectedIndexPath, nil]; self.selectedIndexPath = indexPath; [tableView reloadRowsAtIndexPaths: toReload withRowAnimation: UITableViewRowAnimationMiddle]; } #pragma mark - #pragma mark Memory management - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } - (void)viewDidUnload { } - (void)dealloc { [super dealloc]; } @end 

Если вы не хотите перезагружать ячейку (вы хотите сохранить существующую ячейку и просто resize и, вероятно, добавить / удалить некоторые подзаголовки), тогда просто выполните трюк beginUpdates / endUpdates в файле didSelectRowAtIndexPath :, и вызовите какой-либо метод на вашу ячейку, чтобы вызвать изменение макета. beginUpdates / endUpdates предложит tableView повторно запросить высоты для каждой ячейки – так что обязательно верните правильное значение.

Создайте class, который подclassы UITableviewcell в вашем проекте. Создайте этот class ‘nib и установите его родительский class в свой проект с помощью tableview и переопределите его –

 (void)setSelected:(BOOL)selected animated:(BOOL)animated 

Напишите методы contractCell () и expandCell () в этом classе и укажите высоту ячеек, которые вы хотите использовать в методе expandCell. Вызовите эти методы соответствующим образом на основе некоторых флагов, установленных для идентификации, когда ячейка находится в расширенном состоянии или состоянии контракта. Используйте

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

метод обработки выбранных ячеек.

Замените функцию cellForRowAtIndexPath на эту.

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (isSearching && indexPath.row == selectedIndex) { static NSString *CellIdentifier = @"SearchCell"; CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; UILabel *theText = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, cell.contentView.bounds.size.width -20, 22.0)]; theText.text = @"Title Text"; [cell.contentView addSubview:theText]; UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0, 10 + 46.0, cell.contentView.bounds.size.width - 20, 40.0)]; textField.borderStyle = UITextBorderStyleLine; [cell.contentView addSubview:textField]; UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 88.0, cell.contentView.bounds.size.width - 20, 22.0)]; testLabel.text = [NSString stringWithFormat:@"Some text here"]; [cell.contentView addSubview:testLabel]; [theText release]; [textField release]; [testLabel release]; return cell; } else { static NSString *CellIdentifier = @"Cell"; CustomTableCell *cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; [cell setCustomTitle:[timeZoneNames objectAtIndex:indexPath.row] detail:[timeZoneNames objectAtIndex:indexPath.row]]; return cell; } } 

создать массив wof словарь, который имеет ключ Select_sts, который равен 0 в начале, когда щелкните его изменение 1 accourding u change table

 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 40.0)]; UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero]; headerLabel.backgroundColor = [UIColor clearColor]; headerLabel.opaque = NO; headerLabel.textColor = [UIColor blackColor]; headerLabel.highlightedTextColor = [UIColor whiteColor]; headerLabel.font = [UIFont boldSystemFontOfSize:16]; headerLabel.frame = CGRectMake(5.0, 10.0, 300.0, 20.0); headerLabel.text=[NSString stringWithFormat: @"PNR %@",[[record objectAtIndex:section] objectForKey:@"number"]]; customView.backgroundColor=[UIColor whiteColor]; btn_openClose.tag=section+10000; btn_openClose.backgroundColor=[UIColor clearColor]; // [btn_openClose setImage:[UIImage imageNamed:@"down_arrow.png"] forState:UIControlStateNormal]; [btn_openClose addTarget:self action:@selector(collapseExpandButtonTap:) forControlEvents:UIControlEventTouchUpInside]; [customView addSubview:btn_openClose]; } - (void) collapseExpandButtonTap:(id) sender{ int indexNo=[sender tag]-10000; // NSLog(@"total_record %@",[total_record objectAtIndex:indexNo]); NSMutableDictionary *mutDictionary = [[total_record objectAtIndex:indexNo] mutableCopy]; if([[mutDictionary objectForKey:@"Select_sts"] integerValue]==0) [mutDictionary setObject:[NSNumber numberWithInt:1] forKey:@"√"]; else [mutDictionary setObject:[NSNumber numberWithInt:0] forKey:@"Select_sts"]; [total_record replaceObjectAtIndex:indexNo withObject:mutDictionary]; // [table_view beginUpdates]; // [table_view reloadData]; // [table_view endUpdates]; NSMutableIndexSet *indetsetToUpdate = [[NSMutableIndexSet alloc]init]; [indetsetToUpdate addIndex:indexNo]; // [indetsetToUpdate addIndex:<#(NSUInteger)#>] // You can add multiple indexes(sections) here. [table_view reloadSections:indetsetToUpdate withRowAnimation:UITableViewRowAnimationFade]; } 
  • Координаты текстуры OpenGL в пиксельном пространстве
  • UITextField: перемещение вида при появлении клавиатуры
  • IPhone / IPad: Как получить ширину экрана программно?
  • Как я могу перебирать все подпункты UIView, а также их подзоны и их подпрограммы
  • Лучшая библиотека Cocoa / Objective-C Wrapper для SQLite на iPhone
  • UIPopoverPresentationController на iOS 8 iPhone
  • Как resize UIModalPresentationFormSheet?
  • target переопределяет настройки FRAMEWORK_SEARCH_PATHS
  • Как получить счетчик ссылок NSObject?
  • Как -performSelector: withObject: afterDelay: работать?
  • Почему NSError нуждается в двойной косвенности? (указатель на указатель)
  • Interesting Posts

    Ближайшая точка на кубической кривой Безье?

    Текст размыт на внешнем дисплее обычного DPI с дисплеем для ноутбука Windows 8.1 и ноутбука с высоким разрешением

    Правильно ли упорядочен порядок std :: pair ?

    Студия Android Studio занимает слишком много времени для создания

    Как добавить JTable в JPanel с нулевой компоновкой?

    Хосту ‘xxx.xx.xxx.xxx’ не разрешено подключаться к этому серверу MySQL

    Самый быстрый способ заменить NA в большой таблице данных.

    Отправлять только видеовыход с помощью кабеля HDMI

    Как определить, включено ли «Мобильные сетевые данные» (даже при подключении через WiFi)?

    Приложение для мониторинга всех приложений, использующих Интернет в Mac OS X

    Динамически отключать ядра мощным способом?

    Темный прозрачный слой над QMainWindow в Qt

    Строгое правило сглаживания и указатели ‘char *’

    Компьютер просыпается сам по себе, но источник пробуждения неизвестен

    Как представить значение времени только в .NET?

    Давайте будем гением компьютера.