I am using collectionView in my app.
I have label inside my collectionViewCell.
I want to set frame to that label.
My code is:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
menuCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.lblTag.frame = cell.contentView.frame;
cell.lblTag.text = [arrMenu objectAtIndex:indexPath.row];
return cell;
}
But this frame is works after i scroll collection view.
how can i reload collection view so that label frame set when collectionView display.
you can reload the collection view in viewDidAppear
-(void)viewDidAppear:(BOOL)animated
{
[self.yourcollectionView_outLet reloadData];
}
in my case it work for me.
you can try to change frame in main queue
dispatch_async(dispatch_get_main_queue(), ^{
cell.lblTag.frame = cell.contentView.frame;
});
Related
I have a UICollectionView and I add from my cellForItemAtIndexPath 12 cells. When I do scroll on this to see down cells, all functions is preserved, but when I do scroll to go up again, some cells don't execute the function loaded in didSelectItemAtIndexPath.
I set disabled some rows. But not the row that I clicked Why could be this? Could be a bad prepare for reuse cell?
I'm trying the reuse function, but this only affect drawing the cell wrong or on the another position and the function added in didSelectItemAtIndexPath not work:
[self.myCollectionView reloadData];
[self.myCollectionView layoutIfNeeded];
NSArray *visibleItems = [self.myCollectionView indexPathsForVisibleItems];
NSIndexPath *currentItem = [visibleItems objectAtIndex:0];
NSIndexPath *nextItem = [NSIndexPath indexPathForItem:currentItem.item + 1 inSection:currentItem.section];
[self.myCollectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
WHen I do scroll and the do click to one cell, this not open my secondViewController, I think that this cell is gettin a wrong index that was disabled.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyViewController *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
switch ([indexPath row]) {
case 0:
titleCell= #"Title0";
detailCell=#"Detail0";
if([indexPath row]==2){
[cell setUserInteractionEnabled:NO];//Here I set disable Could be the problem caused by this??
}
[cell.image setHidden:YES];
cell.image.contentMode = UIViewContentModeScaleAspectFit;
break;
//Here other cases with the same structure
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[collectionView deselectItemAtIndexPath:indexPath animated:NO];
MySecondClass *secondClass = [self.storyboard instantiateViewControllerWithIdentifier:#"myVC"];
[self.navigationController pushViewController:secondClass animated:YES];
}
-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
//Here assign yellow background color to first row and white color to the second row
}
And in my cell class I added the prepareForReuse but this not work...
- (void)prepareForReuse {
[super prepareForReuse];
[self removeFromSuperview];
[self setNeedsLayout];
}
The problem lies on this piece of code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyViewController *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"myCell" forIndexPath:indexPath];
switch ([indexPath row]) {
case 0:
titleCell= #"Title0";
detailCell=#"Detail0";
if([indexPath row]==2){
[cell setUserInteractionEnabled:NO];//Here I set disable Could be the problem caused by this??
}
[cell.image setHidden:YES];
cell.image.contentMode = UIViewContentModeScaleAspectFit;
break;
return cell;
}
Because cells are reusable. So the cell that you disabled earlier (For example cell0) will continue to be reused. When you scroll, that cell0 will become cell11 for example. However, its setting is still disabled.
You need to add a else statement to remove the disabled setting like this.
if([indexPath row]==2){
[cell setUserInteractionEnabled:NO];//Here I set disable Could be the problem caused by this??
}
else{
[cell setUserInteractionEnabled:YES];
}
When a cell scrolls off the screen it is potentially deallocated or (more likely) recycled, so any state you have in that cell is not persisted once its off screen. The solution is that you should check if a cell is selected and update its appearance in cellForRowAtIndexPath. You can just have didSelectItemAtIndexPath and didDeselectItemAtIndexPath call reloadRowsAtIndexPath and cellForRowAtIndexPath will handle all of the highlighting appearance logic in one place.
I've set up a Collection View in my storyboard and set its delegate and data source to the view controller, put an ImageView inside of a cell, and have even changed the background of it, but I can't get it to show an image. I've tried adding a button to reload the data, but when I click it nothing happens so I don't think the image is even being passed.
I made sure that my cell and image view has an identifier and I'm using the following code to try to populate the collection view:
View.h file:
__weak IBOutlet UICollectionView *CollectionView;
View.m file
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:302];
UIImage * image = [UIImage imageNamed:#"sunset.jpeg"];
[imageView setImage:image];
return cell;
}
I'm missing something obvious here as this isn't a difficult task.
I have my Collection view in storyboard (amongst other views), with the prototype cell's reuse id being "Cell", and a UILabel in that cell, with a tag of 100.The code (boilerplate):
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 4;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
UILabel *label = (UILabel *)[cell viewWithTag:100];
label.text = #"Hello";
return cell;
}
The code is within a UICollectionViewController, as it should.
When i run, the view appears yet no cells or text are visible.
A NSLog in the cellForItemAtIndexPath confirms that it is called, 4 times.
I've even changed the prototype cell's background color which shows that not even the cell's are appearing.
In the viewDidLoad, it calls: [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
What am i missing?
Use like this:
Instead of registerClass: use registerNib:
static NSString *identifier = #"Cell";
if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
[self.collection registerNib:[UINib nibWithNibName:#"CollectionPhotoItem" bundle:nil] forCellWithReuseIdentifier:identifier];
}
else{
[self.collection registerNib:[UINib nibWithNibName:#"CollectionPhotoItem_ipad" bundle:nil] forCellWithReuseIdentifier:identifier];
}
make sure you are under any-any ratio in your storyboard
if you are working with any other configuration and you tried to use the simulation it might not show up
for example if you use regular width and compact hight and then tried to use the simulator in your Xcode all your work will not show up !
I have a very frustrating problem with UICollectionView and its dequeuing mechanism.
In a nutshell, I have a custom UIView with a label inside. I set this up as the selection background view in my custom cell as follows:
//My Custom Cell Class
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
_selectionView = (MyCustomView *)[[[NSBundle mainBundle] loadNibNamed:#"MyNibName" owner:self options:nil] objectAtIndex:0];
self.selectedBackgroundView = _selectionView;
[self bringSubviewToFront:_selectionView];
}
return self;
}
Note that all the layout work, etc for both the cell and selectedBackgroundView is done in the nibs.
Whenever the cell is selected, I'd like to set custom text in the label for selectionView so in my custom cell I also have the following method:
//In my Custom cell class
- (void) setSelectedViewLabelText:(NSString *)paramText{
if(!self.isSelected){
return;
}
self.selectionView.label.text = paramText;
}
To set the text I have in my UICollectionViewController:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCellClass *selectedCell = (MyCellClass *)[self.collectionView cellForItemAtIndexPath:indexPath];
[selectedCell setSelectedViewLabelText:someString];
}
The problem is that whenever the UICollectionView recycles the cell, it inits them again and obviously the setSelectedViewLabelText method isn't called.
I have an annoying feeling that I may have to track the selected indexPaths and enumerate through them to see if a cell is selected and call the method, but I have potentially large data sets and can foresee how this will become a performance problem.... any ideas?
Thanks in advance!
Keep track of your selected cell, like:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCellClass *selectedCell = (MyCellClass *)[self.collectionView cellForItemAtIndexPath:indexPath];
[selectedCell setSelectedViewLabelText:someString];
selectedIndexPath = indexPath;
}
In cellForItemAtIndexPath check indexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//.......
if([selectedIndexPath isEqual:indexPath]){
[cell setSelectedViewLabelText:someString];
}
return cell;
}
Hope this helps.. :)
I am using collectionView in my App. I am setting image for the cell backgroundView in didSelect delegate. But When i select one cell indexPath the image is getting set for 3 cell indexPath. When i scroll the collectionView the images are getting changed randomly? Please Help me. thanks in advance.
- (void)viewDidLoad
{
[super viewDidLoad];
[collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:uio];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section
{
return 50;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"index %#",indexPath);
UICollectionViewCell *cell = [collection cellForItemAtIndexPath:indexPath];
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
}
That's because you reuse your cell. An option would be to have an dictionary variable to say that your cell has been selected and reset the image if it has not been.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"index %#",indexPath);
UICollectionViewCell *cell = [collection cellForItemAtIndexPath:indexPath];
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
[selectedDictionary setObject:[NSNumber numberWithBool:YES] forKey:[NSNumber numberWithInteger:indexPath.row]];
}
Then in your cellForItemAtIndexPath method you would check that value
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
BOOL selected = [[selectedDictionary objectForKey:[NSNumber numberWithInteger:indexPath.row]] boolValue];
if(selected){
cell.backgroundView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"download.jpg"]];
}else{
cell.backgroundView = nil;
}
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
Of course if you use some kind of object as model, it would appropriate to have a selected variable in here, you won't need a nsdictionary any more.
The Problem is dequeueReusableCellWithReuseIdentifier.
When you scroll UICollectionview then cell are reused that is problem
add Collectionview inside scrollview.
Try this Inside:
Scroll_View is Your Scroll View
collection is Your Collectionview
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
self.Scroll_View.contentSize = CGSizeMake(self.view.frame.size.width, collectionView.contentSize.height);
CGRect fram_For_Collection_View = self.collection_view.frame;
fram_For_Collection_View.size.height = collectionView.contentSize.height;
self.collection.view.frame = fram_For_Collection_View;
}
Your -collectionView:didSelectItemAtPath: is adding a new image view to the cell. Nothing is removing that image view when the cell is reused. So, when you say:
UICollectionViewCell *cell = [collection dequeueReusableCellWithReuseIdentifier:uio
forIndexPath:indexPath];
in your -collectionView:cellForItemAtIndexPath:, you're may get back some cell that already has one or more image views.
My suggestion would be to add the image view to the cell in the cell prototype, perhaps in your storyboard or in the cell's initializer. Have your -collectionView:cellForItemAtIndexPath: set the image for that image view to the correct image for the given path.
What's happening is that UICollectionView reuses cells. So in didSelectItemAtIndexPath: you set the cell background, but then the UICollectionView reuses that same cell as needed (and you're not resetting the cell.backgroundView in cellForItemAtIndexPath:).
The way to fix this is to maintain an NSIndexSet of selected cells. In didSelectItemAtIndexPath: you can add the index of the item that was selected, and then force a reload of that item by calling reloadItemsAtIndexPaths. Then, in your cellForItemAtIndexPath: check the index set to see if the selected index is included, and if so, set the backgroundView of the cell.
I had the same issue few days ago & I posted a question here. Here is the answer I got & it works for me.
Collection View Cell multiple item select Error
And also if you are using a custom cell you can add this code to the init method of that cell & it will work too.
CGFloat borderWidth = 6.0f;
UIView *bgView = [[UIView alloc] initWithFrame:frame];
bgView.layer.borderColor = [UIColor redColor].CGColor;
bgView.layer.borderWidth = borderWidth;
self.selectedBackgroundView = bgView;