Вы можете анимировать изменение высоты на UITableViewCell при выборе?

голоса
361

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

Это возможно?

Задан 20/01/2009 в 04:17
источник пользователем
На других языках...                            


21 ответов

голоса
833

Я нашел действительно простое решение этой , как побочный эффект к UITableViewя работал на .....

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

[tableView beginUpdates];
[tableView endUpdates];

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

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

Ответил 14/01/2010 в 12:42
источник пользователем

голоса
56

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

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

Ответил 26/04/2011 в 00:25
источник пользователем

голоса
19

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

@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];
    }
}
Ответил 05/08/2013 в 17:02
источник пользователем

голоса
12

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 подпрыгивает, чтобы изменить его.

Ответил 07/05/2009 в 00:24
источник пользователем

голоса
10

Я решил с 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];
}
Ответил 14/11/2014 в 13:20
источник пользователем

голоса
10

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

Ответил 02/08/2014 в 23:52
источник пользователем

голоса
2
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;
}
Ответил 15/08/2016 в 16:32
источник пользователем

голоса
2

просто записка для кого-то вроде меня ищет для добавления «Детали» на пользовательской ячейке.

[tableView beginUpdates];
[tableView endUpdates];

Сделал отличную работу, но не забывайте , чтобы просмотреть ячейки «урожай». Из Interface Builder выберите Cell -> Content View -> из инспектора свойств выберите « Клип подвид »

Ответил 25/03/2015 в 20:08
источник пользователем

голоса
2

Попробуйте это для расширения 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;
}
Ответил 24/09/2014 в 06:41
источник пользователем

голоса
1

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

tableView.performBatchUpdates(nil, completion: nil)

Apple, говорит, что касается beginUpdates / endUpdates: «Используйте performBatchUpdates (_:. Завершающие метод :) вместо этого один всякий раз, когда это возможно»

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

Ответил 19/11/2018 в 16:47
источник пользователем

голоса
1

Heres более короткая версия 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
  }
Ответил 30/05/2017 в 23:36
источник пользователем

голоса
1

Swift Версия ответа Саймон Ли.

// 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()
            }
        }
    }
}
Ответил 07/06/2016 в 15:30
источник пользователем

голоса
0

Swift 4 и выше

добавьте ниже код в вас didselect метод строки делегата Tableview в

tableView.beginUpdates()
tableView.setNeedsLayout()
tableView.endUpdates()
Ответил 23/11/2018 в 11:53
источник пользователем

голоса
0

Входы -

tableView.beginUpdates () tableView.endUpdates () эти функции не будут называть

FUNC Tableview (_ Tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}

Но, если вы делаете, tableView.reloadRows ( по адресу: [selectedIndexPath в IndexPath], с: .none)

Это будет вызывать Func Tableview (_ Tableview: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} эта функция.

Ответил 28/03/2018 в 11:08
источник пользователем

голоса
0

Swift версия ответа Саймон Ли :

tableView.beginUpdates()
tableView.endUpdates()

Имейте в виду , что вы должны изменить свойства высоты ДО endUpdates() .

Ответил 08/02/2018 в 14:11
источник пользователем

голоса
0

Да, это возможно.

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:так обращаться соответствующим образом .

Ответил 01/08/2016 в 11:29
источник пользователем

голоса
0

Проверьте этот метод после прошивки 7 и более поздних версий.

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}

Улучшения были внесены в эту прошивке 8. Мы можем установить его в качестве свойства самого представления таблицы.

Ответил 04/03/2016 в 12:10
источник пользователем

голоса
0

Я использовал @ удивительный ответ Джой, и она прекрасно работала с прошивкой 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];

}

Я надеюсь, что все это помогло вам.

Ответил 19/11/2015 в 21:00
источник пользователем

голоса
0

Вот мой код пользовательского 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's 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;
}
Ответил 10/11/2015 в 02:14
источник пользователем

голоса
-1

Я просто решить эту проблему с помощью небольшого хака:

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 :-)

Ответил 20/08/2009 в 21:18
источник пользователем

голоса
-1

Получить indexpath строки, выбранной. Обновить таблицу. В методе heightForRowAtIndexPath из UITableViewDelegate, установить высоту строки, выбранную на разную высоту, и для других вернуть нормальную высоту строки

Ответил 21/01/2009 в 16:13
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more