Можете ли вы изменить изменение высоты на 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;
}