ios - tableviewcontroller - La celda seleccionada de UITableView no permanece seleccionada cuando se desplaza
uitableview custom cell swift 4 (10)
Tengo problemas con las celdas de vista de tabla que no mantienen su estado "seleccionado" al desplazar la tabla. Aquí está el código relevante:
@property (nonatomic, strong) NSIndexPath *selectedIndexPath;
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedIndexPath = indexPath;
//do other stuff
}
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCustomCell_iPhone* cell = [tableView dequeueReusableCellWithIdentifier:@"MyCustomCell_iPhone"];
if (cell == nil)
cell = [[[NSBundle mainBundle] loadNibNamed:@"MyCustomCell_iPhone" owner:self options:nil] objectAtIndex:0];
if ([indexPath compare: self.selectedIndexPath] == NSOrderedSame) {
[cell setSelected:YES animated:NO];
}
return cell;
}
Y para la celda:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected) {
self.selectedBg.hidden = NO;
}else{
self.selectedBg.hidden = YES;
}
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
self.selectedBg.hidden = NO;
}else{
self.selectedBg.hidden = YES;
}
}
¿Cómo puedo conseguir que la celda seleccionada quede resaltada? Si lo muevo fuera de la pantalla, cuando se desplaza hacia atrás en la pantalla, aparece en su estado no seleccionado (con su Bg seleccionado oculto).
EDITAR: Al eliminar el método setHighlighted de la celda se soluciona el problema. Sin embargo, eso significa que no obtengo un estado resaltado al presionar la celda de la tabla. Me gustaría saber la solución a esto.
¿Ha intentado comparar las filas de las rutas de índice en lugar del objeto de ruta de índice completo?
if ((indexPath.row == self.selectedIndexPath.row) && (indexPath.section == self.selectedIndexPath.section)) {
[cell setSelected:YES animated:NO];
}
Aquí está la solución que se me ocurrió, y ni siquiera se siente mal.
1) Implemente -scrollViewWillBeginDragging:
and -scrollViewWillEndDragging:withVelocity:targetContentOffset:
y resalte manualmente la celda de la fila seleccionada (si la hay) durante el desplazamiento.
Los míos se ven así:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollview {
self.scrollViewIsDragging = YES;
if( [self.tableView indexPathForSelectedRow] ) {
[[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]] setHighlighted:YES];
}
}
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
self.scrollViewIsDragging = NO;
if( [self.tableView indexPathForSelectedRow] ) {
[[self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]] setHighlighted:NO];
}
}
La propiedad scrollViewIsDragging
está allí para que in -tableView:cellForRowAtIndexPath:
podemos asegurarnos de que las celdas recién eliminadas de la cola tengan el resaltado adecuado (por ejemplo, si la celda de la fila seleccionada se desplaza a la pantalla después de haber estado fuera de la pantalla). La parte pertinente de ese método se ve así:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ... cell creation/configuration ...
if( self.scrollViewIsDragging && [[tableView indexPathForSelectedRow] isEqual:indexPath]) {
[cell setHighlighted:YES animated:NO];
}
}
…Y ahí lo tienes. La celda de la fila seleccionada permanecerá resaltada durante el desplazamiento.
Envié una respuesta rápida a eso aquí: https://.com/a/35605984/3754003
En ella, también explico por qué sucede esto.
Estoy usando Xcode 9.0.1 y Swift 4.0. Encontré que los siguientes códigos resolvieron mi marca de selección cuando las celdas estaban fuera de pantalla y atrás:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell.isSelected {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
}
Sé que mi método no es muy ortodoxo pero parece funcionar. Aquí está mi solución:
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if cell.selected {
cell.selected = true
} else {
cell.selected = false
}
}
También debes implementar todos los métodos que mencionaste en tu publicación (@soleil)
Si quieres lograr lo mismo en Swift, aquí tienes el código. Por cierto, estoy usando Xcode 7.2 con Swift 2.1.
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if cell.selected == true{
cell.selected = true
cell.backgroundColor = UIColor.blackColor()
}else{
cell.backgroundColor = tableViewCellColor //Don''t panic its my own custom color created for the table cells.
cell.selected = false
}
}
Haz otra personalización lo que quieras ..
Gracias..
Espero que esto haya ayudado.
Solución Swift 3, 2017.
Solucioné el problema con esta simple línea de código:
cell.isSelected = tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false
Dentro del método tableView (tableView: cellForRowAt indexPath :) :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Dequeue a reusable cell
if let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID") {
cell.isSelected = tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false
// Now you can safely use cell.isSelected to configure the cell
// ...your configurations here
return cell
}
return UITableViewCell()
}
Tenía el mismo problema, la vista de accesorios de la celda seleccionada desaparecía en el desplazamiento. Mi compañero de trabajo encontró bastante truco para este problema. El motivo es que en iOS 7 en el evento touchesBegan, UITableView anula la selección de la celda seleccionada y selecciona la celda que se ha bajado. En iOS 6 no sucede y en el desplazamiento seleccionado la celda permanece seleccionada. Para obtener el mismo comportamiento en iOS 7 intente:
1) Habilita la selección múltiple en tu tableView.
2) Vaya a tableView delegate method didSelectRowAtIndexPath , y deseleccione la celda con el código:
NSArray *selectedRows = [tableView indexPathsForSelectedRows];
for(NSIndexPath *i in selectedRows)
{
if(![i isEqual:indexPath])
{
[tableView deselectRowAtIndexPath:i animated:NO];
}
}
¡Arreglado mi problema! Espero que sea útil, lo siento por mi pobre Inglés por cierto.
UITableViewCell tiene una propiedad BOOL " seleccionada ". Cada vez que cargue la celda, verifique el estado de la selección y realice la selección o la deselección correspondiente de la siguiente manera en la definición cellForRowAtIndexPath:
if (cell.selected) {
// Maintain selected state
}
else{
// Maintain deselected state
}
iOS 7/8 anula la selección de la celda cuando comienza el desplazamiento (como señaló Alexander Larionov).
Una solución más simple para mí fue implementar este método UIScrollViewDelegate en mi ViewController:
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
NSInteger theRow = [self currentRowIndex]; // my own method
NSIndexPath *theIndexPath = [NSIndexPath indexPathForRow:theRow inSection:0];
[self.myTableView selectRowAtIndexPath:theIndexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
}
Esto funciona porque mi viewController es el delegado de UITableView, y UITableView hereda de UIScrollView.