8

我正在创建一个应用程序,我在工具栏上有一个按钮,可以选择集合视图中的所有项目。

但我面临的问题是,当我点击按钮时,它只选择那些在屏幕上可见的项目。这是由于 CELL REUSE 功能。

有什么方法可以选择所有单元格,即使是当前对用户不可见的单元格?

谢谢J

4

6 回答 6

19

即使使用单元重用,这也是可能的。您可以通过以下方式选择第一部分中的所有单元格:

for (NSInteger row = 0; row < [self.collectionView numberOfItemsInSection:0]; row++) {
    [self.collectionView selectItemAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] animated:NO scrollPosition:UICollectionViewScrollPositionNone];
}

如果您有超过 1 个部分,只需使用另一个嵌套的 for 循环来遍历所有部分。

于 2014-08-31T23:24:43.690 回答
4

我遇到了同样的问题,我想显示照片并允许用户选择多张照片,带有全选和全选选项。事实证明 [self.collectionView selectItemAtIndexPath:] 不适用于选择所有单元格。

所以我最终与数据源一起维护了一个单独的状态标志。在我的例子中,每个单元格显示一张照片,所以我必须维护一个单独的 BOOL 数组,其中每个元素代表数据源数组中相应照片的当前选择状态。

请看下面的代码:(来源:http ://heliumapps.weebly.com/blog/uicollectionview-and-cell-selection )

@interface PhotosViewController() {
    BOOL *selectedStates; //cell selection states boolean array [C-language array]
    /* Let us assume that we have an array for data source, named  "myDataSourceArray".
       For each element in the array, the correspomding element in selectedStates represents
       the selection state of the cell.
   */
}

//load data source
-(void)loadDataSource {
       //init the data source array (myDataSourceArray) and populate it with data

      //free up the previously allocated memory for selecteStates, if any (in case you reuse this view controller)
      if(selectedStates) {
        free(selectedStates);
        selectedStates = nil;
      }

       //initilaize the selection states of all cells to NO
       selectedStates = malloc(myDataSourceArray.count*sizeof(BOOL));
            for(NSUInteger i = 0; i < self.myDataSourceArray.count; i++) {
                selectedStates[i] = NO;
            }
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    PhotoViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:self.reuseIdentifier
                                                                            forIndexPath:indexPath];
    //populate cell with required data & images to display
    [cell setPhoto:myDataSourceArray[indexPath.item]];

    //configure cell for selection state
    [cell configureCellForSelectionState:selectedStates[indexPath.item]];

    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
        [self toggleSelectionOfCellAtIndex:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
        [self toggleSelectionOfCellAtIndex:indexPath];
}

-(void)toggleSelectionOfCellAtIndex:(NSIndexPath*)indexPath{
    MyCollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
    selectedStates[indexPath.item] = !selectedStates[indexPath.item];
    [cell configureForSelectionState];
}

//method to select/deselect all photos
- (void) setStateForAllPhotos:(BOOL)flag {
    for(NSUInteger i = 0; i < self.myDataSourceArray.count; i++) {
        selectedStates[i] = flag;
    }
    [self.collectionView reloadData];  //on main thread
}


/* below method in the cell's implementation  */
-(void) configureForSelectionState:(BOOL)flag {
       if(flag) {
                  //configure cell for selected state
                  [cell.layer setBorderColor:[UIColor greenColor].CGColor];
                  [cell.layer setBorderWidth:2];
    } else {
               //configure cell for deselected state
    }
}
于 2016-04-05T03:56:48.597 回答
4

为 Swift 3 更新

更新了 Gasper Kolenc 对 swift 3 的回答,以供将来使用,如果有人在 swift 3 中寻找这个答案。

  for row in 0..<self.collectionView!.numberOfItems(inSection: 0) {
    self.collectionView!.selectItem(at: IndexPath(row: row, section: 0), animated: false, scrollPosition: .none)
}
于 2016-10-26T10:40:49.503 回答
2

使用单元重用时不可能选择所有单元。

由于单元重用,在任何时候存在的实际单元的数量比当前可见的单元的数量多几个。即 6 个可见的单元格是大约 8 个单元格存在。

您可以找出有多少可见单元格

NSArray *visiblePaths = [self.collectionView indexPathsForVisibleItems];

解决方案是将selected值存储在 UICollectionView 数据源中,并在自定义单元格时使用该值cellForItemAtIndexPath

于 2013-11-11T22:31:28.077 回答
2

UICollectionView为选择和取消选择创建了一个简单的扩展:

extension UICollectionView {

    /// Iterates through all sections & items and selects them.
    func selectAll(animated: Bool) {
        (0..<numberOfSections).flatMap { (section) -> [IndexPath]? in
            return (0..<numberOfItems(inSection: section)).flatMap({ (item) -> IndexPath? in
                return IndexPath(item: item, section: section)
            })
        }.flatMap { $0 }.forEach { (indexPath) in
            selectItem(at: indexPath, animated: true, scrollPosition: [])
        }

    }

    /// Deselects all selected cells.
    func deselectAll(animated: Bool) {
        indexPathsForSelectedItems?.forEach({ (indexPath) in
            deselectItem(at: indexPath, animated: animated)
        })
    }

}
于 2017-07-24T15:14:38.657 回答
1

斯威夫特 3 解决方案:

stride(from: 0, to: collectionView.numberOfItems(inSection: yourSectionIndex), by: 1)
        .forEach{ collectionView.selectItem(at: IndexPath(row: $0, section: yourSectionIndex), animated: true, scrollPosition: []) }
于 2017-03-14T14:22:10.287 回答