Можете ли вы изменить изменение высоты на UITableViewCell, если оно выбрано?
Я использую UITableView
в своем приложении для iPhone, и у меня есть список людей, принадлежащих к группе. Мне бы хотелось, чтобы при нажатии пользователем на конкретный человек (таким образом, выбрав ячейку) ячейка растет в высоту, чтобы отображать несколько элементов управления пользовательского интерфейса для редактирования свойств этого человека.
Возможно ли это?
Ответы
Ответ 1
Я нашел РЕАЛЬНОЕ ПРОСТОЕ решение для этого как побочный эффект для UITableView
, над которым я работал.....
Сохраняйте высоту ячейки в переменной, которая обычно сообщает исходную высоту с помощью tableView: heightForRowAtIndexPath:
, а затем, когда вы хотите оживить изменение высоты, просто измените значение переменной и вызовите это...
[tableView beginUpdates];
[tableView endUpdates];
Вы обнаружите, что он не выполняет полную перезагрузку, но достаточно, чтобы UITableView
знал, что он должен перерисовывать ячейки, захватывая новое значение высоты для ячейки... и угадайте, что? Это АНИМАТЫ изменения для вас. Сладкое.
У меня есть более подробное объяснение и примеры полного кода в моем блоге... Анимация Изменение высоты ячейки UITableView
Ответ 2
Мне нравится ответ Саймона Ли. Я действительно не пробовал этот метод, но похоже, что он изменит размер всех ячеек в списке. Я надеялся на изменение только той ячейки, которая прослушивается. Я вроде как Симон, но с небольшой разницей. Это изменит внешний вид ячейки при ее выборе. И это оживляет. Это еще один способ сделать это.
Создайте int, чтобы удерживать значение для текущего выбранного индекса ячейки:
int currentSelection;
Тогда:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int row = [indexPath row];
selectedNumber = row;
[tableView beginUpdates];
[tableView endUpdates];
}
Тогда:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath row] == currentSelection) {
return 80;
}
else return 40;
}
Я уверен, что вы можете сделать аналогичные изменения в tableView: cellForRowAtIndexPath: изменить тип ячейки или даже загрузить файл xib для ячейки.
Подобно этому, currentSelection начнется с 0. Вам нужно будет внести коррективы, если вы не хотите, чтобы первая ячейка списка (по индексу 0) выглядела по умолчанию.
Ответ 3
Добавить свойство для отслеживания выбранной ячейки
@property (nonatomic) int currentSelection;
Задайте значение дозорного значения в (например) viewDidLoad
, чтобы убедиться, что UITableView
начинается в "нормальном" положении
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//sentinel
self.currentSelection = -1;
}
В heightForRowAtIndexPath
вы можете установить нужную высоту для выбранной ячейки
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
int rowHeight;
if ([indexPath row] == self.currentSelection) {
rowHeight = self.newCellHeight;
} else rowHeight = 57.0f;
return rowHeight;
}
В didSelectRowAtIndexPath
вы сохраняете текущий выбор и сохраняете динамическую высоту, если требуется
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// set selection
self.currentSelection = indexPath.row;
// save height for full text label
self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
В didDeselectRowAtIndexPath
установите индекс выбора обратно в значение дозорного и оживите ячейку обратно в обычную форму
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// sentinel
self.currentSelection = -1;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
Ответ 4
reloadData не годится, потому что нет анимации...
Это то, что я сейчас пытаюсь сделать:
NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
Он почти работает правильно. Почти. Я увеличиваю высоту ячейки, и иногда в представлении таблицы появляется небольшая "икота", когда ячейка заменяется, как будто сохраняется какая-то позиция прокрутки в представлении таблицы, новая ячейка (которая является первой ячейкой в таблице) заканчивается слишком высоким смещением, и scrollview отскакивает, чтобы переместить его.
Ответ 5
Я не знаю, что все эти вещи о вызове beginUpdates/endUpdates подряд, вы можете просто использовать -[UITableView reloadRowsAtIndexPaths:withAnimation:]
. Вот пример проекта.
Ответ 6
Я разрешил с помощью reloadRowsAtIndexPaths
.
Я сохраняю в didSelectRowAtIndexPath
выбранную ячейку indexPath ячейки и вызываю reloadRowsAtIndexPaths
в конце (вы можете отправить NSMutableArray для списка элементов, которые вы хотите перезагрузить).
В heightForRowAtIndexPath
вы можете проверить, находится ли indexPath в списке или нет ячейки expandIndexPath и отправить высоту.
Вы можете проверить этот базовый пример:
https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam
Это простое решение.
Я добавлю код, если вы поможете
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath
{
if ([indexPath isEqual:_expandIndexPath])
return 80;
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Celda";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell.textLabel setText:@"wopwop"];
return cell;
}
#pragma mark -
#pragma mark Tableview Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *modifiedRows = [NSMutableArray array];
// Deselect cell
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
_expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
Ответ 7
Попробуйте это для расширения строки indexwise:
@property (nonatomic) NSIndexPath *expandIndexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.expandedIndexPath])
return 100;
return 44;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandIndexPath]) {
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = nil;
} else {
if (self.expandedIndexPath)
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
}
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ViewControllerCellReuseIdentifier];
cell.textLabel.text = [NSString stringWithFormat:@"I'm cell %ld:%ld", (long)indexPath.section, (long)indexPath.row];
return cell;
}
Ответ 8
просто записка для кого-то вроде меня, ищущего добавить "Подробнее" в пользовательскую ячейку.
[tableView beginUpdates];
[tableView endUpdates];
Отличная работа, но не забывайте "обрезать" вид ячеек.
Из Interface Builder выберите ячейку → Просмотр содержимого → из Property Inspector выберите " Подключить клип"
Ответ 9
BOOL flag;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
flag = !flag;
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES == flag ? 20 : 40;
}
Ответ 10
Быстрая версия ответа Саймона Ли.
// MARK: - Variables
var isCcBccSelected = false // To toggle Bcc.
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// Hide the Bcc Text Field , until CC gets focused in didSelectRowAtIndexPath()
if self.cellTypes[indexPath.row] == CellType.Bcc {
if (isCcBccSelected) {
return 44
} else {
return 0
}
}
return 44.0
}
Затем в файле didSelectRowAtIndexPath()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
// To Get the Focus of CC, so that we can expand Bcc
if self.cellTypes[indexPath.row] == CellType.Cc {
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? RecipientTableViewCell {
if cell.tag == 1 {
cell.recipientTypeLabel.text = "Cc:"
cell.recipientTextField.userInteractionEnabled = true
cell.recipientTextField.becomeFirstResponder()
isCcBccSelected = true
tableView.beginUpdates()
tableView.endUpdates()
}
}
}
}
Ответ 11
Вот мой код пользовательского подкласса UITableView
, который расширяет UITextView
в ячейке таблицы без перезагрузки (и потерял фокус клавиатуры):
- (void)textViewDidChange:(UITextView *)textView {
CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
// Check, if text height changed
if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
[self beginUpdates];
// Calculate difference in height
CGFloat difference = textHeight - self.previousTextHeight;
// Update currently editing cell height
CGRect editingCellFrame = self.editingCell.frame;
editingCellFrame.size.height += difference;
self.editingCell.frame = editingCellFrame;
// Update UITableView contentSize
self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);
// Scroll to bottom if cell is at the end of the table
if (self.editingNoteInEndOfTable) {
self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
} else {
// Update all next to editing cells
NSInteger editingCellIndex = [self.visibleCells indexOfObject:self.editingCell];
for (NSInteger i = editingCellIndex; i < self.visibleCells.count; i++) {
UITableViewCell *cell = self.visibleCells[i];
CGRect cellFrame = cell.frame;
cellFrame.origin.y += difference;
cell.frame = cellFrame;
}
}
[self endUpdates];
}
self.previousTextHeight = textHeight;
}
Ответ 12
Я использовал @Joy потрясающий ответ, и он отлично работал с ios 8.4 и XCode 7.1.1.
Если вы хотите, чтобы ваша ячейка переключалась, я изменил значение -tableViewDidSelect на следующее:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell,
//cell is expanded. If tapped again on the same cell,
//cell is collapsed.
if (self.currentSelection==indexPath.row) {
self.currentSelection = -1;
}else{
self.currentSelection = indexPath.row;
}
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
Я надеюсь, что это помогло вам.
Ответ 13
Проверьте этот метод после iOS 7 и более поздних версий.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
Усовершенствования были сделаны в iOS 8. Мы можем установить его как свойство самого представления таблицы.
Ответ 14
Да, возможно.
UITableView
имеет метод делегата didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView animateWithDuration:.6
delay:0
usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
initialSpringVelocity:0
options:UIViewAnimationOptionBeginFromCurrentState animations:^{
cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
[violatedTableView beginUpdates];
[violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
[violatedTableView endUpdates];
}
completion:^(BOOL finished) {
}];
}
Но в вашем случае, если пользователь прокручивает и выбирает другую ячейку, тогда вам нужно, чтобы последняя выбранная ячейка сжималась и расширяла текущую выделенную ячейку reloadRowsAtIndexPaths:
вызывает heightForRowAtIndexPath:
, поэтому обрабатывайте соответственно.
Ответ 15
Вот более короткая версия Simons отвечает за Swift 3. Также позволяет переключать выбор ячейки
var cellIsSelected: IndexPath?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellIsSelected = cellIsSelected == indexPath ? nil : indexPath
tableView.beginUpdates()
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if cellIsSelected == indexPath {
return 250
}
return 65
}
Ответ 16
Получить индексный путь выбранной строки. Перезагрузите стол. В методе heightForRowAtIndexPath UITableViewDelegate задайте высоту строки, выбранной на другую высоту, а остальные верните нормальную высоту строки
Ответ 17
Я просто решил эту проблему с небольшим взломом:
static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;
- (void)onTimer {
cellHeight++;
[tableView reloadData];
if (cellHeight < s_CellHeightEditing)
heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (isInEdit) {
return cellHeight;
}
cellHeight = s_CellHeight;
return s_CellHeight;
}
Когда мне нужно увеличить высоту ячейки, я устанавливаю isInEdit = YES
и вызываю метод [self onTimer]
, и он оживляет рост ячейки, пока не достигнет значения s_CellHeightEditing: -)
Ответ 18
Вы можете использовать этот метод и изменить возвращаемое значение, как вы хотите
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 71;
}