#ios #objective-c #iphone #uitableview #cocoa-touch
#iOS #objective-c #iPhone #uitableview #cocoa-touch
Вопрос:
Я создаю приложение, которое имеет табличный вид. Но я хочу, чтобы это было табличное представление, которое расширяет ячейку при нажатии на нее и закрывает при повторном нажатии.
Но мне было интересно, возможно ли следующее. Когда ячейка не выбрана, вы видите только картинку, заголовок и начало текста. Но как только ячейка будет выбрана, она расширится и покажет еще больше вложенных представлений, то есть изображений.
Возможно ли это? Например, скрыть вложенный просмотр в ячейке, и как только на него нажимают, он становится видимым и выровнен правильным образом? И, конечно, как мне это сделать?
Спасибо!!!
Ответ №1:
Я делал нечто подобное довольно давно. Вы найдете код на github.
Обратите внимание, что это очень грубо, так как это было в мои первые дни iPhone, то есть свойства отсутствуют.
.ч
#import <UIKit/UIKit.h>
@interface FirstViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
NSIndexPath *selectedIndexPath;
NSDictionary *articles;
}
@end
.м
#import "FirstViewController.h"
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
selectedIndexPath = nil;
articles = [[NSDictionary dictionaryWithObject:[NSArray arrayWithObjects:@"one", @"two", @"three",
@"four", @"five", @"six",
@"seven", @"eight", @"nine",
@"ten", @"eleven", nil]
forKey:@"title"] retain];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[selectedIndexPath release];
[articles release];
[super dealloc];
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[articles allKeys] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[articles allKeys] objectAtIndex : section];
}
- (int)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
id key = [[articles allKeys] objectAtIndex:section];
return [[articles objectForKey : key] count];
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ((selectedIndexPath != nil) amp;amp; (selectedIndexPath.row == indexPath.row))
return 80.0;
return 40.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * MyIdentifier = @"MyIdentifier";
UITableViewCell * cell = [self.tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
}
id key = [[articles allKeys] objectAtIndex:indexPath.section];
cell.textLabel.text = [[articles objectForKey:key] objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (selectedIndexPath == indexPath) {
selectedIndexPath = nil;
} else {
selectedIndexPath = indexPath;
}
[self.tableView deselectRowAtIndexPath : indexPath animated : NO];
[tableView beginUpdates];
[tableView endUpdates];
}
@end
Комментарии:
1. Спасибо! Это, безусловно, поможет
2. Вы случайно также не знаете, как изменить содержимое ячейки при нажатии на ячейку? Например .. добавить новый вложенный просмотр и выровнять его по нижней части развернутой ячейки? Спасибо!
3. существует несколько способов настройки ячеек табличного представления. смотрите Руководство по программированию табличного представления . И не забудьте проголосовать.
4. Настройка ячейки без проблем. Но содержимое ячейки должно изменяться при нажатии. Извините, но я не могу проголосовать, пока не наберу 15 баллов…
5. Это просто: в
tableView:cellforRowAtIndexPath:
вы можете проверить, является ли параметрindexPath
темselectedIndexPath
, и соответствующим образом настроить свою ячейку.
Ответ №2:
Да, я делаю это в приложении, над которым сейчас работаю.
Вам необходимо отслеживать состояние, в котором находится ячейка, открытая или закрытая. Если одновременно может быть открыта только 1 ячейка, вы можете сделать это, просто сохранив ссылку на текущий indexPath . Если одновременно может быть открыто несколько ячеек, вам понадобится массив логических значений, который отслеживает, открыто или закрыто каждое из них.
В heightForRowAtIndexPath просто верните правильную высоту в зависимости от того, открыта строка или закрыта.
В cellForRowAtIndexPath, если строка закрыта, скройте все содержимое, которое не должно быть видно при ее закрытии. Представления все еще могут быть там, но они должны быть установлены на hidden = YES
.
Наконец, в didSelectRowAtIndexPath задайте для указанного пути индекса значение open, если он был закрыт, и closed, если он был открыт, затем перезагрузите ячейку с помощью [tableView reloadRowsAtIndexPaths:]
. Если вы разрешаете открывать одновременно только 1 ячейку, просто установите текущий путь к открытому индексу на тот, который был выбран, и перезагрузите как тот, который был выбран, так и тот, который был открыт ранее.
Комментарии:
1. Отличный ответ, попробую это сразу!
2. Привет, Гендолкари, я не совсем понимаю, как мне нужно установить скрытое состояние. Нужен ли мне просто пользовательский выбор, т.Е. if (cellState == @»closed){secondLabel.hidden = ДА} else{secondLabel.hidden = НЕТ}? Не вызывается ли cellForRowAtIndexPath только один раз, поскольку он использует идентификатор повторного использования? Спасибо!
3. Да, просто установите secondLabel.hidden = ДА. Однако не используйте «==» для сравнения двух строк; вам нужно использовать
isEqualToString:
метод.cellForRowAtIndexPath:
вызывается каждый раз, когда ячейка перезагружается или отображается на экране. reuseidentifier используется только для того, чтобы остановить[UITableViewCell alloc]
повторный вызов; ноcellForRowAtIndexPath:
метод вызывается в любом случае.4. Хорошо … я только что попробовал это. Странно то, что когда я вставляю этот код: if ([cellState isEqualToString: @»open»]) { secondLabel.hidden = NO; NSLog(@»ridk»); }else { NSLog (@»ridk»); secondLabel.hidden = YES; } Он регистрируется только 5 раз при загрузке приложения (поскольку в нем 5 строк) После этого журнал больше не вызывается. Даже если я обновлю данные