Highlight collection cell when selected - ios

I am trying to highlight a selected collection cell in UICollectionView with yellow border so user can see which one is currently selected. I tried this:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
FilterCell *filterCell = (FilterCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"FilterCell" forIndexPath:indexPath];
filterCell.window.backgroundColor = [UIColor yellowColor];
filterCell.backgroundColor = [UIColor yellowColor];
NSLog(#"hello");
}
There are 2 empty pixels around UIImageView inside UICollectionViewCell so it should work but it doesn't.
It is logging "hello" but the border stays black. See this screenshot:

You are getting the cell in the wrong way
FilterCell *filterCell = (FilterCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"FilterCell" forIndexPath:indexPath];
will dequeue a cell which is not used right now or allocate a new one with the specified identifier.
Use
FilterCell *filterCell = (FilterCell *)[collectionView cellForItemAtIndexPath:indexPath];
instead.
Anyway a cleaner solution would be to set the backgroundView and selectedBackgroundView properties of the cell, without touching the backgroundProperty color (that will stay clear as default). In this way you can avoid the delegate method and achieve the same behavior.

Do a reloadItemsAtIndexPaths: there instead, then in cellForItemAtIndexPath, check if [[collectionView indexPathsForSelectedItems] containsObject:indexPath] If true, change the cell's attributes there.

This may help you:
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"YOUR_FILE_NAME.png"]];

-This code may help you to change background colour of selected cell
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cvCell" forIndexPath:indexPath];
if (cell.selected) {
cell.backgroundColor = [UIColor blueColor]; // highlight selection
}
else
{
cell.backgroundColor = [UIColor redColor]; // Default color
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor blueColor]; // highlight selection
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *datasetCell =[collectionView cellForItemAtIndexPath:indexPath];
datasetCell.backgroundColor = [UIColor redColor]; // Default color
}

Related

UicollectionViewCell on cell select change Border colour

I have a custom UICollectionVIewCell. When the user selects a cell I want the border of the cell to be Red in color and when the user de-selects it I want to clear-color the border of the cell.
How is this possible?
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
CustomeCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.backgroundColor=[UIColor redColor];
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
CustomeCollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.backgroundColor=[UIColor clearColor];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
NSString *img =[[images objectAtIndex:indexPath.row]valueForKey:#"imageName"];
cell.backgroundView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:img]];
cell.layer.borderWidth=10;
cell.layer.borderColor=[UIColor greenColor].CGColor;
return cell;
}
This is working code in my app. Make sure that there is borderwidth if you giving bordercolor.
Use built in methods of UICollectionViewCell class.
You need override setHighlighted: method.
- (void)setHightlighted:(BOOL)highlighted {
[super ....];
self.something = highlighted ? red : blue;
}
You can try:
cell.layer.borderColor
to change color border

How to change UICollectionViewCell's background outside of cell

How to change iOS UICollectionViewCell background outside of the cell?
For instance, I have a view controller which implements UICollectionViewDelegate method:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:MY_CELL_REUSE_IDENTIFIER];
}
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:MY_CELL_REUSE_IDENTIFIER forIndexPath:indexPath];
if (condition)
{
[self actionOne];
cell.backgroundColor = [UIColor redColor];
}
else
{
[self actionTwo];
cell.backgroundColor = [UIColor greenColor];
}
return YES;
}
Breakpoints inside of if (condition) statement shows, that desired lines are executed. But, sadly, cells background stays the same...
What is more, I am successfully doing practically the same thing id UICollectionViewDataSource method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:MY_CELL_REUSE_IDENTIFIER forIndexPath:indexPath];
cell.backgroundColor = [UIColor orangeColor];
}
What am I doing wrong?
Try cellForRowAtIndexPath in place ofdequeueReusableCellWithReuseIdentifier.
EDIT: Only in shouldSelectItemAtIndexPath.
Explanation: dequeueReusableCellWithReuseIdentifier will get you a new cell, that you change the background color of, but that cell never gets added to the table so you won't see it. When you use cellForRowAtIndexPath, you will get a cell from the table to edit.
This should do it:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (condition)
{
[self actionOne];
cell.backgroundColor = [UIColor redColor];
}
else
{
[self actionTwo];
cell.backgroundColor = [UIColor greenColor];
}
}

CollectionView Highlights incorrect Cell When Scrolling

I have a UICollectionView. When an user clicks a cell the colour of the cell changes to red. I have coded the above part and it works perfectly.
However, when I scroll below, other cells in the collection view has got highlighted with the colour red. I am sure that it hasn't been selected but only highlighted.
How can I solve this.
My code is as follows:
cellForItemAtIndexPath Method
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"cell";
ViewCell *vc = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
vc.vciv.image = [arrayOfImages objectAtIndex:indexPath.row];
return vc;
}
didSelectItemAtIndexPath Method
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if([items containsObject:allItem[indexPath.row]] ){
UICollectionViewCell *c =[collectionView cellForItemAtIndexPath:indexPath];
c.backgroundColor = [UIColor clearColor];
} else {
UICollectionViewCell *c =[collectionView cellForItemAtIndexPath:indexPath];
c.backgroundColor = [UIColor redColor];
}
As the collection view cells get reused, you need to make sure a dequeued cell is not highlighted in the cellForItemAtIndexPath: method:
UICollectionViewCell *vc = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
vc.backgroundColor = [UIColor clearColor];
This code will clear the cell's background always when dequeuing. If you need to preserve the highlighting, you need to store the indexPaths of the cells that you want to have highlighted, and check for the current cell being in that list.
EDIT
It seems that your items variable is well suited to do that.
So you would do:
UICollectionViewCell *vc = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
vc.backgroundColor = [items containsObject:allItem[indexPath.row]] ? [UIColor redColor] : [UIColor clearColor];

UICollectionViewCell background color change works in cellForItemAtIndexPath but not didSelectItemAtIndexPath

I can change my collection view cell background color in cellforitematindexpath but not in didselectitematindexpath using the code below (i only change the color in one place however). How does this happen? I know that didselectitematindexpath is being called.
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = [cv dequeueReusableCellWithReuseIdentifier:#"CollectionView" forIndexPath:indexPath];
cell.layer.borderWidth=1.0f;
cell.layer.borderColor=[UIColor grayColor].CGColor;
cell.label.text = #"test"
cell.contentView.backgroundColor = [UIColor redColor];
return cell;
}
-(void)collectionView:(UICollectionView *)cv didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"selected cell");
CollectionViewCell *cell = [self collectionView:cv cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor redColor];
}
Several things wrong here.
You're using the wrong method to get the selected cell. Never call the delegate method directly, instead ask the collection view for the cell directly like this:
CollectionViewCell *cell = [cv cellForItemAtIndexPath:indexPath];
You're modifying the cell in a place where those modifications will not persist. When you scroll and that cell gets reused, the color will get wiped out. Instead you should call reloadItemsAtIndexPaths: when the cell gets selected, and have some code in collectionView:cellForRowAtIndexPath that checks the selected property of the cell and sets the color you want based on that. That way, the layout will remain consistent when you scroll and cells are reused.
use this..
self.collectionView.allowsMultipleSelection = YES;
then..
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath**
{
static NSString *identifier = #"Cell";
RecipeViewCell *cell = (RecipeViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:[recipeImages[indexPath.section] objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame-2.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (shareEnabled) {
NSString *selectedRecipe = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[selectedRecipes addObject:selectedRecipe];
}
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (shareEnabled) {
NSString *deSelectedRecipe = [recipeImages[indexPath.section] objectAtIndex:indexPath.row];
[selectedRecipes removeObject:deSelectedRecipe];
}
}

Reusing cell causes unwanted behaviour when updating cell view

I want ot set a border to a selected cell, i save a cell property that represents the selected one and manipulate it:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];
if (indexPath.row==5) {
int r = arc4random() % 6;
eyeArray = [self eyesArrayConfigure][r];
}
[borderedCell.contentView.layer setBorderWidth:0.0f] ;
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
borderedCell = cell;
[borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
[borderedCell.contentView.layer setBorderWidth:3.0f];
}
and the cellForView: (Im usinng 2 types of cell identifiers because one cell contains a label - "Random cell":
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row ==5) {
UICollectionViewCell *randomCell =[collectionView
dequeueReusableCellWithReuseIdentifier:#"randomCell"
forIndexPath:indexPath];
randomCell.backgroundColor = [UIColor purpleColor];
borderedCell = randomCell;
[borderedCell.contentView.layer setBorderColor:self.view.tintColor.CGColor];
[borderedCell.contentView.layer setBorderWidth:3.0f];
return randomCell;
}
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
NSArray *eyeArray = [self eyesArrayConfigure][indexPath.row];
myCell.backgroundView = [[UIImageView alloc] initWithImage:eyeArray[1]];
return myCell;
}
What i get is if a click one cell it will be fine till i scroll and then i get weird behaviour when couple of cells might be with the border.
Thanks for the help.
The solution is to use a view model. You are already doing this for your cells' background views. Apply the same concept for the border.
#interface MyCollectionView ()
#property (nonatomic) NSInteger selectedRow;
#end
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//update self.selectedRow and either reload entire collection view or just the currently selected and previously selected.
self.selectedRow = indexPath.row;
[collectionView reloadData];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *myCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
CGFloat borderWidth = (indexPath.row == self.selectedRow) ? 3.0 : 0.0;
[myCell.contentView.layer setBorderWidth:borderWidth];
return myCell;
}

Resources