¿Cómo se deseleccionan las celdas mediante programación en UICollectionView cuando allowMultipleSelection está habilitado?


Tengo habilitada allowMultipleSelection en una vista de colección. Las células cambian hacia y desde su estados seleccionados cuando se toca. Todo bien. Sin embargo, cuando quiero restablecer toda la vista al estado seleccionado:NO usando el código a continuación, las celdas parecen estar completamente deseleccionadas hasta que realice una nueva selección, momento en el que todas las celdas seleccionadas previamente muestran su estado seleccionado previamente.

Es decir, a pesar de las apariencias, collectionview no está actualizando su lista de selección actual cuando programáticamente deselecciono las celdas

- (void)clearCellSelections {
   for (LetterCell  *cell in self.collectionView.visibleCells) {
        [cell prepareForReuse];
    }
}

En la celda personalizada:

- (void)prepareForReuse
{
    [super prepareForReuse];
    [self setSelected:NO];
}

¿Qué estoy haciendo mal? ¿Hay otra forma de deseleccionar todas las celdas?

Gracias TBlue por echar un vistazo

Author: Steve, 2013-01-21

8 answers

Puedes iterar sobre - [UICollectionView indexPathsForSelectedItems]:

for (NSIndexPath *indexPath in [self.collectionView indexPathsForSelectedItems]) {
    [self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
}
 82
Author: qorkfiend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-22 20:20:10

La forma más sencilla de deseleccionar todas las celdas seleccionadas en un UICollectionView es simplemente pasar nil como primer argumento a collectionView.selectItem(at:, animated:, scrollPosition:). Por ejemplo,

collectionView.selectItem(at: nil, animated: true, scrollPosition: [])

Borrará el estado de selección actual, incluso cuando allowsMultipleSelection == true.

 17
Author: taherh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-16 03:09:51

Se podría decir que UITableViewCell.selected solo establece el 'estado/apariencia visible' de la celda y su contenido. Puede deseleccionar las celdas, iterando sobre todos los indexPaths de la vista de tabla y llamar deselectRowAtIndexPath:animated: para cada uno.

Por ejemplo:

for (int i=0; i < self.myData.count; i++) {
    [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0] animated:YES];
}

EDIT : Estoy totalmente de acuerdo con los comentarios de @BenLings y @JeremyWiebe, que la solución de @qorkfiend es preferible a esta.

 11
Author: fguchelaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-19 15:41:10

Por si acaso esta es una solución simple en Swift:

extension UICollectionView {
    func deselectAllItems(animated animated: Bool = false) {
        for indexPath in self.indexPathsForSelectedItems() ?? [] {
            self.deselectItemAtIndexPath(indexPath, animated: animated)
        }
    }
}
 4
Author: Valentin Shergin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-10 23:55:34

Para la extensión swift 3 se vería así:

import UIKit

extension UICollectionView {
    func deselectAllItems(animated: Bool = false) {
        for indexPath in self.indexPathsForSelectedItems ?? [] {
            self.deselectItem(at: indexPath, animated: animated)
        }
    }
}
 2
Author: KIO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-17 17:20:34

Creé una variable global llamada toggleCellSelection, luego ejecuté esto en la función didSelectItemAt:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print("select cell \(indexPath.row)")

    let cell = collectionView.cellForItem(at: indexPath)
    if (toggleCellSelection == true) {
        toggleCellSelection = false
        cell?.layer.borderWidth = 0
        cell?.layer.borderColor = UIColor.clear().cgColor
    } else {
        toggleCellSelection = true
        cell?.layer.borderWidth = 5
        cell?.layer.borderColor = #colorLiteral(red: 0.8779790998, green: 0.3812967837, blue: 0.5770481825, alpha: 1).cgColor
    }


}
 0
Author: retrovius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-06 20:20:37

No es que esta respuesta sea necesariamente 'la mejor', pero como nadie la mencionó, la agregaré.

Simplemente puede llamar a lo siguiente.

collectionView.allowsSelection = false
collectionView.allowsSelection = true
 0
Author: cnotethegr8,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 07:12:07

Esta es la respuesta de @qorkfiend en Swift

// this is an array of the selected item(s) indexPaths
guard let indexPaths = collectionView.indexPathsForSelectedItems else { return }

// loop through the array and individually deselect each item
for indexPath in indexPaths{
    collectionView.deselectItem(at: indexPath, animated: true)
}
 0
Author: Lance Samaria,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-20 07:21:48