I am using a UICollectionView to display some data. I am having one button on each cell. Now on the button click of at some specific index(ex: 9) I want to change buttons image for all cells. Can some one suggest how to do that?
I would loop through all the visible cells and change the image. For example:
for (CustomCellClass *cell in collectionView.visibleCells) {
[cell.button setImage:[UIImage imageNamed:#"new image"] forState:UIControlStateNormal];
}
For off-screen cells, I would make sure to set the new image in collectionView:cellForItemAtIndexPath: as the user scrolls to those cells.
We can simply add the logic in cellForItemAtIndexPath like this.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
if (self.buttonClicked) { // boolean check
[cell.newButton setImage:buttonClickedImage];
}else {
[cell.newButton setImage:buttonNotClickedImage];
}
return cell;
}
After clicking the button, you can also just reload all visible cells.
[self.collectionView reloadItemsAtIndexPaths:self.collectionView.indexPathsForVisibleItems];
Feel free to suggest edits to make this answer better :)
Related
I have an odd bug, after use tap row cell's image changed. I didn't implement didSelectRowAtIndexPath method, so i guess its just table reloading forces image to redraw.
Here is code:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// Загружаем ячейку из класса, далее подгружаем текст из класса initialData.
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
NewsParseer *news = [self.objectsArray objectAtIndex:indexPath.row];
// Text
cell.textLabel.text = news.text;
// Image
[cell.imageView setImageWithURL:news.urlImage];
return cell;
}
Very simple. Here is screenshots, first - when app launched and load image. Second, when i tap a row.
Obviously i don't want image to resize after user interaction.
For anyone that wondered whats going wrong, there is answer:
I tried to set image to default property of cell, called imageView, but in Storyboard and in my custom class i work with different image view (property that i call myImageView).
Without constraints my UICollectionViewCells load immediately without any problems at all. When I put constraints on in storyboard so the image view is horizontal and vertically centered to the cell, the first image cell does not load. I have to scroll a few times and then back to the beginning for the first image cell to show. Take the constraints off and it goes back to working perfectly fine.
I thought maybe the images weren't getting loaded in time but that doesn't appear to be the case.
What am I missing?
I can put in some code but it is a pretty standard UICollectionView with custom cell inside ViewController.
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CollectionViewCell *cell = (CollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
NSString *imageName = [NSString stringWithFormat:#"%#", [self.urlArray objectAtIndex:indexPath.row]];
[cell setImageName:imageName];
[cell updateCell];
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.collectionView.frame.size;
}
EDIT:
I just removed the navigation bar and the first 2 images were loading behind the nav bar. They are loading in the size of the default prototype CollectionViewCell. Once I scroll away and back to it, it is the expected size.
When you don't put in constraints, IB automatically puts in constraints for you that give you an absolute position and size based on the frame in the storyboard. Chances are good that the constraints you're adding are not doing what you think they are.
Adding [cell layoutIfNeeded]; right before return cell in cellforitematindexpath fixed it
I am using a UICollectionview to show a lot of Custom cells (250 more or less).
Those cells have a main Image and some text. As the images have to be downloaded from the Internet I am using the external library AsyncImageView to do the lazy load stuff.
But the problem is that the reusable property of the cells are making me crazy.
When I scroll the images appear in the wrong cells. How can I add a tag or something to the images apart from the indexpath to avoid the problem?
Maybe AsyncImageView has a solution to the problem which I ignore ...
Or another alternative would be a better choice?
Any clue?
Thanks in advance
Edit: A simplified version of my code
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
CollectionComercioCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if (cell == nil){
}
else{
[[AsyncImageLoader sharedLoader] cancelLoadingImagesForTarget: cell.myImage];
}
cell.myImage.imageURL = nil;
cell.myImage.image = nil;
cell.myImage.hidden = TRUE;
cell.myImage.imageURL = [[myArray objectAtIndex:indexPath.row] getLogoUrl];
cell.myText.text = [[myArray objectAtIndex:indexPath.row] getName];
cell.myImage.hidden = FALSE;
return cell;
}
CustomCell.m
- (void)prepareForReuse
{
[super prepareForReuse];
self.myImage.image = nil;
}
Make sure you set the image to nil in your cellForRowAtIndexPath: method. This way it will stay at least empty until the new image is loaded.
As you mentioned in your comments to the question that this is works if you scroll slow and not when you scroll fast you could maybe override - (void)prepareForReuse on your custom cell.
But be aware that Apple warns you not to use it for content changes:
For performance reasons, you should only reset attributes of the cell
that are not related to content, for example, alpha, editing, and
selection state. The table view's delegate in
tableView:cellForRowAtIndexPath: should always reset all content when
reusing a cell. If the cell object does not have an associated reuse
identifier, this method is not called. If you override this method,
you must be sure to invoke the superclass implementation.
When I click they,the function of click(shch as show an alert or get into a new view) works fine but the appearance of the cell I clicked don't change.What I can do to make the cell I click get highlighted ?THX~
Add a public method performSelectionAnimations to the definition of MyCollectionViewCell. Then call it from collectionView:didSelectItemAtIndexPath:
-(void)performSelectionAnimations {
...
...
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
[cell performSelectionAnimations];
}
Notice I've taken out the call to [cell setSelected:YES], since that should already be taken care of by the UICollectionView.
You must do it programmatically. Look at :
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CollectionViewPGforIOS.pdf#page18
When you tap on the cell the highlight state change to YES, but you must implement de behaviour (i.e. change background cell on click).
I am building an app similar to iPhone photo app. I am able to show the images in a grid like view using PSUICollectionView. When I tap on a grid cell of collection view a checkbox image should appear. My problem is when I am using following code, I see that multiple random cells are being populated with check box images.
- (void)collectionView:(PSUICollectionView *)collectionView didSelectItemAtIndexPath: (NSIndexPath *)indexPath
{
NSLog(#"%# - %d", NSStringFromSelector(_cmd), indexPath.item);
ImageGridCell *cell = (ImageGridCell *)[collectionView cellForItemAtIndexPath:indexPath];
UIButton *chkboxBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[chkboxBtn setFrame:CGRectMake(60, 60, 30, 30)];
[chkboxBtn setImage:[UIImage imageNamed:#"Checkmark-iPhone.png"] forState:UIControlStateNormal];
[cell addSubview:chkboxBtn];
}
The problem is likely your custom cell has not implemented the prepareForReuse method. As a cell is reused, it may or may not have the check box, depending on if the check box was added on a previous use.
Several ways to address this. One simple way is to add a tag to the ckhboxBtn, and then remove the chkboxBton in the prepareForReuse method. E.g., when adding the check box, add the following:
[chkboxBtn setTag:100];
Then in your UICollectionViewCell class implementation, add/expand the prepareForReuse method:
-(void)prepareForReuse{
[[self viewWithTag:100] removeFromSuperview];
}