Можете ли вы анимировать изменение высоты на UITableViewCell при выборе? - PullRequest
389 голосов
/ 20 января 2009

Я использую UITableView в своем приложении для iPhone, и у меня есть список людей, принадлежащих к группе. Мне бы хотелось, чтобы, когда пользователь нажимает на конкретного человека (выбирая таким образом ячейку), высота ячейки увеличивается, чтобы отобразить несколько элементов управления пользовательского интерфейса для редактирования свойств этого человека.

Возможно ли это?

Ответы [ 21 ]

869 голосов
/ 14 января 2010

Я нашел ДЕЙСТВИТЕЛЬНО ПРОСТОЕ решение этой проблемы как побочный эффект для UITableView, над которым я работал .....

Сохраните высоту ячейки в переменной, которая обычно сообщает исходную высоту через tableView: heightForRowAtIndexPath:, затем, когда вы хотите анимировать изменение высоты, просто измените значение переменной и вызовите это ...

[tableView beginUpdates];
[tableView endUpdates];

Вы обнаружите, что он не выполняет полную перезагрузку, но достаточно для UITableView, чтобы знать, что он должен перерисовать ячейки, захватывая новое значение высоты для ячейки .... и знаете что? Это оживляет изменения для вас. Сладкое.

У меня есть более подробное объяснение и полные примеры кода в моем блоге ... Animate UITableView Изменение высоты ячейки

60 голосов
/ 26 апреля 2011

Мне нравится ответ Саймона Ли. На самом деле я не пробовал этот метод, но похоже, что он изменит размер всех ячеек в списке. Я надеялся на изменение только той ячейки, которая прослушивается. Я вроде сделал это как Саймон, но с небольшой разницей. Это изменит внешний вид ячейки при ее выборе. И это оживляет. Просто еще один способ сделать это.

Создайте 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) выглядела выделенной по умолчанию.

22 голосов
/ 05 августа 2013

Добавить свойство для отслеживания выбранной ячейки

@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];
    }
}
14 голосов
/ 07 мая 2009

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];

Это почти работает правильно. Почти. Я увеличиваю высоту ячейки, и иногда в представлении таблицы происходит небольшой «сбой» при замене ячейки, как будто сохраняется некоторая позиция прокрутки в представлении таблицы, новая ячейка (которая является первой ячейкой). в таблице) заканчивается слишком большим смещением, и представление прокрутки отскакивает, чтобы изменить его положение.

11 голосов
/ 03 августа 2014

Я не знаю, что это за вызовы beginUpdates / endUpdates, вы можете просто использовать -[UITableView reloadRowsAtIndexPaths:withAnimation:] Вот пример проекта .

10 голосов
/ 14 ноября 2014

Я решил с 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];
}
4 голосов
/ 19 ноября 2018

Вместо beginUpdates() / endUpdates() рекомендуемый вызов теперь:

tableView.performBatchUpdates(nil, completion: nil)

Apple говорит относительно beginUpdates / endUpdates: «При возможности используйте метод executeBatchUpdates (_: завершение :) вместо этого».

См .: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

3 голосов
/ 24 сентября 2014

Попробуйте это для расширения индексной строки:

@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;
}
3 голосов
/ 15 августа 2016
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;
}
2 голосов
/ 25 марта 2015

просто заметка для кого-то вроде меня, ищущего добавить "Подробнее" в пользовательской ячейке.

[tableView beginUpdates];
[tableView endUpdates];

Проделал отличную работу, но не забудьте "обрезать" вид ячейки. В Интерфейсном Разработчике выберите «Ячейка» -> «Просмотр содержимого» -> из «Инспектора свойств» выберите « Клип-подпредставление »

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...