ios - uitableviewdatasource - ¿Puede animar un cambio de altura en un UITableViewCell cuando se selecciona?




uitableviewcontroller swift 4 (13)

Acabo de resolver este problema con un pequeño truco:

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

Cuando necesito expandir la altura de la celda, establezco isInEdit = YES y llamo el método [self onTimer] y anima el crecimiento de la celda hasta que alcance el valor de s_CellHeightEditing :-)

Estoy usando un UITableView en mi aplicación de iPhone y tengo una lista de personas que pertenecen a un grupo. Me gustaría que cuando el usuario haga clic en una persona en particular (seleccionando así la celda), la celda crezca en altura para mostrar varios controles de interfaz de usuario para editar las propiedades de esa persona.

es posible?


Agregar una propiedad para realizar un seguimiento de la celda seleccionada

@property (nonatomic) int currentSelection;

Establézcalo en un valor de centinela en (por ejemplo) viewDidLoad , para asegurarse de que UITableView comience en la posición "normal"

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //sentinel
    self.currentSelection = -1;
}

En heightForRowAtIndexPath puede establecer la altura que desee para la celda seleccionada

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int rowHeight;
    if ([indexPath row] == self.currentSelection) {
        rowHeight = self.newCellHeight;
    } else rowHeight = 57.0f;
    return rowHeight;
}

En didSelectRowAtIndexPath , guarda la selección actual y guarda una altura dinámica, si es necesario

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

En didDeselectRowAtIndexPath , didDeselectRowAtIndexPath establecer el índice de selección en el valor de centinela y anime la celda a su forma normal

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {       
        // do things with your cell here

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

Aquí hay una versión más corta de la respuesta de Simons para Swift 3. También permite alternar la selección de la celda

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
  }

Compruebe este método después de iOS 7 y versiones posteriores.

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

Se han realizado mejoras a esto en iOS 8. Podemos configurarlo como propiedad de la propia vista de tabla.


Entradas -

tableView.beginUpdates () tableView.endUpdates () que estas funciones no llamarán

func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}

Pero, si lo hace, tableView.reloadRows (at: [selectedIndexPath! As IndexPath], con: .none)

Llamará a la función tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {} esta función.


Intenta esto es para expandir la fila 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;
}

No sé qué es todo lo que se trata de llamar a beginUpdates / endUpdates en sucesión, solo puede usar -[UITableView reloadRowsAtIndexPaths:withAnimation:] . Aquí hay un proyecto de ejemplo .


Obtener la ruta de índice de la fila seleccionada. Recargar la mesa. En el método heightForRowAtIndexPath de UITableViewDelegate, establezca la altura de la fila seleccionada a una altura diferente y para las demás devuelva la altura de fila normal


Usé la asombrosa respuesta de @ Joy, y funcionó perfectamente con ios 8.4 y XCode 7.1.1.

En el caso de que desee hacer que su celda se pueda cambiar, cambié el -tableViewDidSelect a lo siguiente:

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

}

Espero que algo de esto te haya ayudado.


Versión rápida de la respuesta de Simon Lee :

tableView.beginUpdates()
tableView.endUpdates()

Tenga en cuenta que debe modificar las propiedades de altura ANTES de endUpdates() .


reloadData no es bueno porque no hay animación ...

Esto es lo que estoy tratando actualmente:

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

Casi funciona bien. Casi. Estoy aumentando la altura de la celda, y algunas veces hay un pequeño "problema" en la vista de tabla cuando se reemplaza la celda, como si se estuviera preservando alguna posición de desplazamiento en la vista de tabla, la nueva celda (que es la primera celda) en la tabla) termina con su desplazamiento demasiado alto, y la vista de desplazamiento rebota para reposicionarla.


solo una nota para alguien como yo que busca agregar "Más detalles" en una celda personalizada.

[tableView beginUpdates];
[tableView endUpdates];

Hizo un excelente trabajo, pero no olvide "recortar" la vista de celda. Desde Interface Builder, seleccione su celda -> Vista de contenido -> desde Property Inspector, seleccione " subvista de clips "


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






uitableview