**
I have horizontal CollectionView in which selected cell have orange
gradient color and all other deselected cells gray color i m
using only didselect delegate method but i am getting problem of
multiple cells selected and i have problem with same concept in table
view while scrolling and i have searched a lot but i have not get
proper answer of cell reusability
**
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DateTimeCell * cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:#"DateTimeCellID" forIndexPath:indexPath];
if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath)
{
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = cell.mainView.bounds;
gradient.startPoint = CGPointZero;
gradient.endPoint = CGPointMake(1, 1);
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:238.0/255.0 green:42.0/255.0 blue:123/255.0 alpha:1.0] CGColor],(id)[[UIColor colorWithRed:241.0/255.0 green:90.0/255.0 blue:41.0/255.0 alpha:1.0] CGColor], nil];
[gradient setMasksToBounds:NO];
cell.mainView.backgroundColor = [UIColor clearColor];
[cell.mainView.layer insertSublayer:gradient atIndex:0];
[indexPaths addObject:self.selectedIndexPath];
}
else
{
[cell.mainView setBackgroundColor:[self colorWithHexString:#"383F4A"]];
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
indexPaths = [NSMutableArray arrayWithObjects:indexPath, nil];
if (self.selectedIndexPath)
{
// if we had a previously selected cell
if ([indexPath compare:self.selectedIndexPath] == NSOrderedSame)
{
// if it's the same as the one we just tapped on, then we're unselecting it
NSLog(#"Selected");
}
else
{
// if it's different, then add that old one to our list of cells to reload, and
// save the currently selected indexPath
[indexPaths addObject:self.selectedIndexPath];
self.selectedIndexPath = indexPath;
}
}
else
{
// else, we didn't have previously selected cell, so we only need to save this indexPath for future reference
self.selectedIndexPath = indexPath;
}
dispatch_async(dispatch_get_main_queue(), ^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
});
}
take a global selectedIndexPath globaly like below
NSIndexPath *selectedIndexPath = [[NSIndexPath alloc] indexPathForRow:0 inSection:0];
wrilte below code in delegate methods
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
DateTimeCell * cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:#"DateTimeCellID" forIndexPath:indexPath];
if self.selectedIndexPath == indexPath
{
// do what you want to do with your selected cell
}
else
{
// do what you want to do with your deselected cell
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
self.selectedIndexPath = indexPath
[self.collectionView reloadData];
}
Related
I am facing the same issue Multiple selections Issue
Here is my code which I have done.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
RCCollectionCell* cell = [_channelCollectionView dequeueReusableCellWithReuseIdentifier:#"RC" forIndexPath: indexPath];
cell.layer.cornerRadius = 5.0f;
cell.layer.borderWidth=1.0f;
cell.layer.borderColor=[UIColor lightGrayColor].CGColor;
if (indexPath.row < [_fC count]){
[cell setChannel:_favoriteChannels[indexPath.row]];
[_channelCollectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
} else {
//NSLog(#"Error cell %d requested only %d channels in incident", (int)indexPath.row, (int)[_incident.channels count]);
}
return cell;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
RCCollectionCell* cell = [_channelCollectionView dequeueReusableCellWithReuseIdentifier:#"RC" forIndexPath: indexPath];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
RCCollectionCell* cell = (RCCollectionCell*)[collectionView cellForItemAtIndexPath:indexPath];
Channel* channel = [self getChannelForIndexPath:indexPath];
if ([_upload.channels containsObject:channel.uuid]) {
[_upload.channels removeObject:channel.uuid];
cell.selectedImage.hidden = YES;
} else {
[self.view makeToast:channel.name duration:1.5 position:CSToastPositionCenter];
[_upload.channels addObject:channel.uuid];
cell.selectedImage.hidden = NO;
}
[collectionView deselectItemAtIndexPath:indexPath animated:YES];
}
My Problem is cell.selectedImage.hidden = NO; when I click on any cell and when I scroll the collectionview I can see that another cell is also affected with selectedimage.hidden = no.
Please suggest me some solutions to resolve this issue.
Thanks in advance.
EDIT:
selectedImage is a checkmark image which I am using to check and uncheck the cell.
First you create a NSMutableArray to store the selected collectionview indexpaths.
NSMutableArray *SelectedIndexes = [[NSMutableArray alloc]init];
and add the indexpath in the if conditoin of didselect method
[SelectedIndexes addObject:indexPath];
And remove the indexpath inside "else" condition of didselect method.
if ([SelectedIndexes containsObject:indexPath]) {
[SelectedIndexes removeObject:indexPath];
}
In your cellForItemAtIndexPath method check for the selected indexpath.
if ([SelectedIndexes containsObject:indexPath]) {
cell.selectedImage.hidden = YES;
}
else {
cell.selectedImage.hidden = NO;
}
My collection view is like upper, when the selected cell all disappear I was invoke an action:
- (IBAction)clearAction:(UIButton *)sender {
for (CustomCell *cell in self.buy_code_cv.visibleCells) {
if (cell.selected) {
[cell setSelected: NO];
}
}
}
In the Custom Cell's .m file: I override the setSelected: method:
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
//self.selected = !selected;
if (selected) {
self.backView.backgroundColor = APP_COLOR;
self.number_label.textColor = [UIColor whiteColor];
self.multiple_label.textColor = [UIColor whiteColor];
}
// uncheck
else {
self.backView.backgroundColor = [UIColor whiteColor];
self.number_label.textColor = HexRGB(0x999999);
self.multiple_label.textColor = HexRGB(0xcccccc);
}
if (self.delegate && [self.delegate respondsToSelector:#selector(didSelectedCustomCell:)]) {
[self.delegate didSelectedCustomCell:self];
}
}
How to solve this issue in UICollectionView?
A UICollectionViewCell is a merely a representation of the collection view state, it does not hold the state of the collection view. An item that is offscreen may be selected, in which case there won't even be a UICollectionViewCell instance for that item.
Rather than updating the cell directly, you need to tell the collection view to deselect the item and have it take care of updating any on-screen cells.
- (IBAction)clearAction:(UIButton *)sender {
for (NSIndexPath *indexPath in self.buy_code_cv.indexPathForSelectedItems) {
[self.buy_code_cv deselectItemAtIndexPath:indexPath animated:YES];
}
}
My suggestion is that maintain array of index when you select any cell.
In this method
-(void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.arraySelected containsObject:[NSNumber numberWithInt:indexPath.row]])
{
[self.arraySelected removeObject:[NSNumber numberWithInt:indexPath.row]];
}
else
{
[self.arraySelected addObject:[NSNumber numberWithInt:indexPath.row]];
}
[collectionView reloadData];
}
And Write this code is in this method
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
if ([self.arraySelected containsObject:[NSNumber numberWithInt:indexPath.row]]) {
self.backView.backgroundColor = APP_COLOR;
self.number_label.textColor = [UIColor whiteColor];
self.multiple_label.textColor = [UIColor whiteColor];
}
// uncheck
else {
self.backView.backgroundColor = [UIColor whiteColor];
self.number_label.textColor = HexRGB(0x999999);
self.multiple_label.textColor = HexRGB(0xcccccc);
}
return cell;
}
So pretty much, when I try to scroll my UICollectionView while I a cell is selected, shown by a thin orange border, when I scroll back a different cell has the border. I read that it had something to do with cell's being reused. Anyways I found some code online, but just been having a hard time adapting it to multiple selection.
Found a solution to this problem all you have to do is make an array of selected cells and add or remove borders in
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
method
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//each cell is refreshed when page is scrolled
//Matches every cell to see if it is selected or not and adds or removes borders accordinglly
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:indexPath.item];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
[cell.layer setBorderColor:[UIColor orangeColor].CGColor];
cell.layer.borderWidth = 5.0f;
}
else
{
[cell.layer setBorderColor:[UIColor clearColor].CGColor];
cell.layer.borderWidth = 0.0f;
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//Adds cells indexPath to selectedCellsArray and adds border around the cell right away
NSLog(#"selected");
UICollectionViewCell*selectedCell = [collectionView cellForItemAtIndexPath:indexPath];
if (![selectedCellsArray containsObject:[NSString stringWithFormat:#"%d",indexPath.item]] ) {
[selectedCellsArray addObject:[NSString stringWithFormat:#"%d",indexPath.item]];
[selectedCell.layer setBorderColor:[UIColor orangeColor].CGColor];
selectedCell.layer.borderWidth = 5.0f;
NSLog(#"add");
}
NSLog(#"keep track of array:%#", selectedCellsArray);
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
//Removes cells indexPath from selectedCellsArray and removes border form cell right away
NSLog(#"deselected");
UICollectionViewCell*deselectedCell = [collectionView cellForItemAtIndexPath:indexPath];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%d",indexPath.item]] )
{
[selectedCellsArray removeObject:[NSString stringWithFormat:#"%d",indexPath.item]];
[deselectedCell.layer setBorderColor:[UIColor clearColor].CGColor];
deselectedCell.layer.borderWidth = 0.0f;
NSLog(#"remove");
}
}
I try to change status of image in the cell of the UICollectionView object...
this is a part of my code:
-(UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
cell *aCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
[aCell.myImage setImage:[UIImage imageWithContentsOfFile:self.imageArray[indexPath.item]]];
if (aCell.selected) {
aCell.myImage.layer.borderWidth = 1.0;
aCell.myImage.layer.borderColor = [UIColor blackColor].CGColor;
aCell.mySelect.hidden = NO;
} else {
aCell.myImage.layer.borderWidth = 0.0;
aCell.myImage.layer.borderColor = nil;
aCell.mySelect.hidden = YES;
}
return aCell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Select");
cell *selectedCell= [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
if (selectedCell.selected) {
[selectedCell.mySelect setImage:[UIImage imageNamed:#"select.png"]];
selectedCell.myImage.layer.borderWidth = 1.0;
selectedCell.myImage.layer.borderColor = [UIColor blackColor].CGColor;
selectedCell.mySelect.hidden = NO;
} else {
[selectedCell.mySelect setImage:nil];
selectedCell.myImage.layer.borderWidth = 0.0;
selectedCell.myImage.layer.borderColor = nil;
selectedCell.mySelect.hidden = YES; }
}
when i tap any cell, the value select changes, but view object does not refresh.
you need to refresh your row selected with this methos from your didSelectItemAtindexPath method
- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
I think you should override selected/highlighted property in your custom UICollectionViewCell subclass for this task instead of using reload.
cell *selectedCell= [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
This code will create a NEW cell! Your viewController is not contain this cell!
You should use correct method for getting selected cell:
[yourContentView cellForItemAtIndexPath:indexPath];
Why you are dequeue Cell, when cell is selected .
write following code
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
NSLog(#"Select");
cell *selectedCell= (cell *)[collectionView cellForItemAtIndexPath:indexPath];
[selectedCell.mySelect setImage:(selectedCell.selected) ? [UIImage imageNamed:#"select.png"]: nil];
[collectionView reloadItemsAtIndexPaths:indexPath];
}
I am trying to select a cell in UICollectionView, it gets selected but on scroll down it selects the some other cell on the bottom and scroll up it shows some other to be selected.
Below is the code which I am using didSelectItemAtIndexPath
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *newIndex = indexPath;
cell = (CustomCollectionCell *)[collectionView cellForItemAtIndexPath:newIndex];
NSString *strId = [[masterArray valueForKey:#"id"]objectAtIndex:indexPath.row];
NSString *tempIndexRow = [NSString stringWithFormat:#"%ld",(long)indexPath.row];
NSLog(#"%#, %#,%d ,%#, %d", strId,tempIndexRow,cell.imageView.tag,[boolArray objectAtIndex:indexPath.row],indexPath.row);
if (strId && [[boolArray objectAtIndex:indexPath.row] isEqualToString:#"False"] && cell.imageView.tag == indexPath.row) {
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
[boolArray replaceObjectAtIndex:indexPath.row withObject:#"True"];
}
else{
cell.selectedImage.image = Nil;
[boolArray replaceObjectAtIndex:indexPath.row withObject:#"False"];
}
}
This is what I select for the first time
This is what I get when I scroll down
Thanks
You need to set selected item index store in to one array and at cellForRowIndex time check this array index with indexPath.row like bellow:-
selectedCellsArray alloc this array at ViewDIdLoad method
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
cell = (CustomCollectionCell *)[collectionView cellForItemAtIndexPath:newIndex];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%d",indexPath.row]] )
{
[selectedCellsArray removeObject:[NSString stringWithFormat:#"%d",indexPath.row]];
cell.selectedImage.image = Nil;
}
else
{
[selectedCellsArray addObject:[NSString stringWithFormat:#"%d",indexPath.row]];
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
}
and
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *rowNsNum = [NSNumber numberWithUnsignedInt:indexPath.row];
if ( [selectedCellsArray containsObject:[NSString stringWithFormat:#"%#",rowNsNum]] )
{
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
else
{
cell.selectedImage.image = Nil;
}
}
It is not selecting another cell. Problem is mostlikely due to you reusing cells and not reintializing them correctly when they come back on the screen. When Cells not visible, it unloaded to save memory.
So better check this condtion as well in cellForItemAtIndexPath datasource
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//You cell initialization code.
if ([[boolArray objectAtIndex:indexPath.row] isEqualToString:#"True"] ) {
cell.selectedImage.image = [UIImage imageNamed:#"select.png"];
}
else{
cell.selectedImage.image = Nil;
}
}