I'm currently facing a problem where my collectionView changes the order of my items when they scroll off the screen and switches the selected cell. At the moment they're organized so that they scrolls vertically (and there are two items side by side):
Here is my - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"FriendCell";
FriendsCell *cell = (FriendsCell *)[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
//Friend Object
PFUser *friend = [self.friendsArray objectAtIndex:indexPath.item];
cell.friendId = currentFriend.objectId;
//Setup Cell
if (!cell.isSelected) {
cell.layer.backgroundColor = [UIColor whiteColor].CGColor;
} else {
cell.layer.backgroundColor = FlatGreen.CGColor;
}
//Set Profile Image
if (!cell.profileImageView) {
cell.profileImageView = [UIImageView new];
cell.profileImageView.image = [UIImage imageNamed:#"ProfileImagePlaceholder"];
[cell addSubview:cell.profileImageView];
}
//Set Username
if (!cell.usernameLabel) {
//Set Username Label
cell.usernameLabel = [UILabel new];
cell.usernameLabel.text = friend[#"username"];
cell.usernameLabel.textColor = [UIColor lightGrayColor];
[cell addSubview:cell.usernameLabel];
} else {
if (cell.isSelected) {
cell.usernameLabel.textColor = [UIColor whiteColor];
} else {
cell.usernameLabel.textColor = [UIColor lightGrayColor];
}
}
return cell;
}
didSelectItemAtIndexPath:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
//Determine the selected friend by using the indexPath
PFUser *selectedFriend = [self.friendsArray objectAtIndex:indexPath.item];
//Add the selected friend's objectId to our array
[self.friendsToAdd addObject:selectedFriend.objectId];
//Show Selected View
FriendsCell *currentCell = (FriendsCell *)[collectionView cellForItemAtIndexPath:indexPath];
//Animate
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
//Update
currentCell.layer.backgroundColor = FlatGreen.CGColor;
currentCell.profileImageView.alpha = 0.0;
currentCell.usernameLabel.textColor = [UIColor whiteColor];
} completion:nil];
}
didDeselectItemAtIndexPath:
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
//Determine the selected friend by using the indexPath
PFUser *deselectedFriend = [self.friendsArray objectAtIndex:indexPath.item];
//Remove the deselected friend's objectId from our array
[self.friendsToAdd removeObject:deselectedFriend.objectId];
//Show Deselected View
FriendsCell *currentCell = (FriendsCell *)[collectionView cellForItemAtIndexPath:indexPath];
//Animate
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionTransitionFlipFromBottom animations:^{
//Update Card
currentCell.layer.backgroundColor = [UIColor whiteColor].CGColor;
currentCell.profileImageView.alpha = 1.0;
currentCell.usernameLabel.textColor = [UIColor lightGrayColor];
} completion:nil];
}
If anyone can spot why this is happening, I'd really appreciate it!
Try
dequeueReusableCellWithReuseIdentifier:nil
Related
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;
}
I have a UICollectionView , Under that collection view i have custom UICollectionViewCell with A Image view and A label. I am trying to change color of label text of selected cell. But every time i am changing the color of label text, its changing in multiple cells . Can anyone help me with the issue?
The code i am using :
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *te =[self.smilyObject objectAtIndex:indexPath.row];
self.wallPostMood =[te objectForKey:#"title"];
NSLog(#"%#",self.wallPostMood);
EffectsCollectionViewCell *efCell = (EffectsCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
efCell.title.textColor = [UIColor orangeColor];
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
EffectsCollectionViewCell *efCell = (EffectsCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
efCell.title.textColor = [UIColor grayColor];
}
I also have tried :
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *te =[self.smilyObject objectAtIndex:indexPath.row];
self.wallPostMood =[te objectForKey:#"title"];
NSLog(#"%#",self.wallPostMood);
NSArray* visibleCellIndex = collectionView.indexPathsForVisibleItems ;
for(NSIndexPath * path in visibleCellIndex){
EffectsCollectionViewCell *efCell = (EffectsCollectionViewCell *)[collectionView cellForItemAtIndexPath:path];
if([efCell.title.text isEqualToString:self.wallPostMood]){
// NSLog(#"%#",efCell);
// NSLog(#"got");
efCell.title.textColor = [UIColor orangeColor];
}else{
efCell.title.textColor = [UIColor grayColor];
}
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//NSLog(#"enter category cell");
CategoryViewCell* cell = (CategoryViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
[cell.imgCat setImage:[UIImage imageNamed:[categoryImages objectAtIndex:indexPath.row]]];
[cell.labelCatName setText:[[NSString stringWithFormat:#"%#", [catName objectAtIndex:indexPath.row]] capitalizedString]];
if([categories[[NSString stringWithFormat:#"%d",(int)indexPath.row]] isEqual:#YES]) {
//NSLog(#"set border");
cell.layer.borderColor = [UIColor redColor].CGColor;
cell.layer.borderWidth = 3;
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
CategoryViewCell* cell = (CategoryViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
cell.layer.borderWidth = 3;
cell.layer.borderColor = [UIColor redColor].CGColor;
//NSLog(#"%i", (int)indexPath.item);
categories[[NSString stringWithFormat:#"%i", (int)indexPath.item]] = #YES;
}
-(void) collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
CategoryViewCell* cell = (CategoryViewCell*)[collectionView cellForItemAtIndexPath:indexPath];
cell.layer.borderColor = [UIColor clearColor].CGColor;
categories[[NSString stringWithFormat:#"%i", (int)indexPath.item]] = #NO;
}
The problem:
The above code will show you a collectionView with cells that are selected at default. However, the states of these selected cells are not selected. So I have to tap twice to deselect them because the first tap is to select them, and second tap is to deselect them.
I have tried to set selected for cell but it doesn't work either. The cell will have a red border whenever the user selected a cell and clearColor when the user deselect the cell.
I tried:
cell.selected = YES;
But this permanently gives a collectionView Cell a red border.
And add it in cellForItemAtIndexPath method still doesn't do the trick.
[self collectionView:collectionView didSelectItemAtIndexPath:indexPath];
CategoryViewCell.m
-(void) setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected];
//NSLog(#"Pass Select Animated");
if (selected) {
self.flagHighlight = NO;
self.selected = NO;
self.layer.borderColor = [UIColor clearColor].CGColor;
self.layer.borderWidth = 3;
} else {
self.flagHighlight = YES;
self.selected = YES;
self.layer.borderColor = [UIColor redColor].CGColor;
self.layer.borderWidth = 3;
}
}
How would I pre-select a cell when the view is loaded programmatically?
Or even better just change the state of the cell being selected.
Thanks in advance.
Ending up answering my own problem.
so I use [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
in cellForItemAtIndexPath.
Serve the purpose nicely.
I'm building an app in iOS and I want the Cells in my CollectionView to highlight when touched, pretty much like the normal buttons. How can I achieve this in the didSelectItemAtIndexPath:(NSIndexPath *)indexPath method?
Try something like this:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
.....
if (cell.selected) {
cell.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:153/255.0 alpha:1]; // highlight selection
}
else
{
cell.backgroundColor = [UIColor clearColor]; // Default color
}
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:153/255.0 alpha:1]; // //cell.lblImgTitle.text = #"xxx";
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
}
If you subclassed the cell class, put this in your .m file
- (void)setSelected:(BOOL)selected
{
if(selected)
{
self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:0.5];
}
else
{
self.backgroundColor = [UIColor whiteColor];
}
}
try this
cell.selectedBackgroundView.backgroundColor = [UIColor greenColor];
why can not change the background color through the cocoa pods?I new a user-defined collectionView cell class`
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
CHSMenuControlCell *cell = (CHSMenuControlCell*)[collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:255/255.0 green:255/255.0 blue:153/255.0 alpha:1]; // //cell.lblImgTitle.text = #"xxx";
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
CHSMenuControlCell *cell = (CHSMenuControlCell *)[collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
}
I have been looking around here for a answer with no success so now ill make a try my self.
Im trying to make a UicollectionView with different cells containing images + an animation with the cells.
I want the cells to do "random flipping" with my images (5 different images)
UIViewAnimationOptionTransitionFlipFromLeft
in a loop with 5-6 sec delay.
the animation i have for the moment is this:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[cell.superview bringSubviewToFront:collectionView];
[UIView transitionWithView:cell
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[UICollectionViewCell commitAnimations];
cell.transform = CGAffineTransformMakeRotation(0.0);
}
completion:^(BOOL finished) {}];
}
I know that i shouldn't use the didSelectItemAtIndexPath, but i used it just to see if the animation were right.
If you check at this video u can see what i mean, on the windows 8 phone. Youtube video
Ok, I was interested on this idea so I prototyped some code. I needs to be specifically tailored to your needs but it can be a good start. Firstly, you will need to subclass your UICollectionViewCell in order to connect an IBOutlet to your imageView inside the cell. Then you can reference my code snippet to get you started.
- (void)viewDidLoad
{
[super viewDidLoad];
self.imageList = #[#"img1.png", #"img2.png", #"img3.png", #"img4.png"];
}
// This assumes your images are inside your Bundle.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(updateCells:)
userInfo:nil
repeats:YES];
}
- (void)updateCells:(NSTimer *)timer
{
NSArray *visibleIndexPaths = [self.collectionView indexPathsForVisibleItems];
for (NSIndexPath *indexPath in visibleIndexPaths) {
SubclassCollectionViewCell *cell = (SubclassCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
[UIView transitionWithView:cell
duration:1.0f
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
cell.imageView.image = [self randomImage];
} completion:nil];
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
return cell;
}
- (UIImage *)randomImage
{
NSInteger randomNumber = arc4random() % [self.imageList count];
return [UIImage imageNamed:[self.imageList objectAtIndex:randomNumber]];
}
Update:
If you want only one cell at a time to randomly flip, you will need to take out the for loop in the updateCells method. Instead, try this:
- (void)updateCells:(NSTimer *)timer
{
NSArray *visibleIndexPaths = [self.collectionView indexPathsForVisibleItems];
NSInteger randomIndex = arc4random() % [visibleIndexPaths count];
NSindexPath *randomIndexPath = [NSIndexPath indexPathForItem:randomIndex inSection:0];
SubclassCollectionViewCell *cell = (SubclassCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
[UIView transitionWithView:cell
duration:1.0f
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
cell.imageView.image = [self randomImage];
}
completion:nil
];
}
Edited post:
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
int interval = 5+(rand() % 6);
int section = 0;
int row = (arc4random() % self.cellList.count);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
CollectionCell *cell = (CollectionCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
[NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(updateCells:)
userInfo:cell
repeats:NO];
NSLog(#"seconds: %d", interval);
NSLog(#"row: %d", row);
}
- (void)updateCells:(NSTimer *)timer{
CollectionCell* cell = [timer userInfo];
[UIView transitionWithView:cell
duration:1.0f
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
cell.collectionImageView.image = [self randomImage];
} completion:nil];
int interval = 5+(rand() % 5);
NSLog(#"speed: %d", interval);
int section = 0;
int row = (arc4random() % self.cellList.count);
NSLog(#"row: %d", row);
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
CollectionCell *newCell = (CollectionCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
[NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:#selector(updateCells:)
userInfo:newCell
repeats:NO];}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.cellList.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect frame = self.collectionView.frame;
[collectionView setFrame:frame];
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ReuseID" forIndexPath:indexPath];
[collectionView setNeedsDisplay];
[self cellTitleAndBackground:cell indexPath:indexPath];
return cell;
}
- (void)cellTitleAndBackground:(CollectionCell *)cell indexPath:(NSIndexPath *)indexPath {
// Get title
NSString *name = [[NSString alloc] initWithFormat:#"%#", self.cellList[indexPath.row]];
// Create title background
UILabel *titleBackground = [[UILabel alloc] initWithFrame:CGRectMake(5, 70, 70, 30)];
titleBackground.backgroundColor = [UIColor blackColor];
titleBackground.alpha = 0.6f;
titleBackground.tag = 70;
[self removeReusedLabel:cell tag:70];
[cell addSubview:titleBackground];
// Create titleLabel
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 70, 70, 30)];
titleLabel.textColor = [UIColor whiteColor];
titleLabel.font = [UIFont boldSystemFontOfSize:12];
titleLabel.text = name;
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.tag = 72;
[self removeReusedLabel:cell tag:72];
[cell addSubview:titleLabel];
}
-(void)removeReusedLabel:(CollectionCell *)cell tag:(int)tag {
UILabel *foundLabelBackground = (UILabel *)[cell viewWithTag:tag];
if (foundLabelBackground) [foundLabelBackground removeFromSuperview];
}
- (UIImage *)randomImage
{
// Random image for cells
NSInteger randomNumber = arc4random() % [self.imageList count];
return [UIImage imageNamed:[self.imageList objectAtIndex:randomNumber]];
}