custom cell for UICollectionView - objective-c

I need to create an app which has a list of items, each item has an image a title, a subtitle a price and a description and I need 2 items per line (so I can't use a UITableView)
Is it possible to use a UICollectionView with custom cell in order to have the result I want or should I search another solution?
The custom cell layout should be like this:

You totally can !
Just create your custom UICollectionViewCell, then go in the "cellForItemAtIndexPath" method in order to use it.
Hope this help :)

1, create a xib file in the subclass of UIcollectionViewCell
2, register your xib in controller's viewdidload fun
[mCollectionView registerNib:[UINib nibWithNibName:#"CollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"Cell"];
3,
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
return cell;
}

You can definitely customise your UICollectionView's Cell. But you will have to do following steps as well:
Register your Custom Cell to your collection view :
[self.collectionView registerClass:[YourCustomClass class]
forCellWithReuseIdentifier:#"CustomCell"];
Secondly, inside your method : cellForItemAtIndexPath, you will have to call custom cell like this (as you do in tableView's custom cell too):
YourCustomClass *cell = (YourCustomClass *)[collectionView
dequeueReusableCellWithReuseIdentifier:#"CustomCell" forIndexPath:indexPath];
Here is a tutorial to make custom UICollectionView Cell

Related

How to change the background colour of a UICollectionViewCell based on a given value

I have a view controller which contains a UICollectionView. It has re-use identifier ValveCell specified for the prototype cell. It is using a custom subclass of UICollectionViewCell called ValveViewCell.
I have put a couple of text labels on the prototype cell using the Storyboard and I can get the different values to display in multiple cells no problem. There are currently 4 cells, displaying info from 4 different valves.
All I want to do is change the background colour of the cell depending on whether the valve is turned on or off (a boolean value which I can successfully test on).
I am using this code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ValveViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ValveCell" forIndexPath:indexPath];
Valve *valve = [valveArray objectAtIndex:indexPath.row];
cell.valveID.text = [valve.valveID stringValue];
cell.valveLabel.text = valve.valveLabel;
cell.valveStatus.text = valve.status;
if ([valve isOn]) {
[cell setBackgroundColor:[UIColor greenColor]];
} else {
[cell setBackgroundColor:[UIColor redColor]];
}
return cell;
}
The problem is that it does change the background colour, but it changes every single cell's background colour instead of just the current cell. Any ideas? Thanks in advance!
Easy Fix! Put this as the first line in your method!
ValveViewCell *cell = [[ValveViewCell alloc] init]
and then change
ValveViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ValveCell" forIndexPath:indexPath];
to
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ValveCell" forIndexPath:indexPath];
You're referencing the same cell for the whole collectionView so initializing each cell will fix your issue.

UICollectionView, Images inside a cell does not load until the cell is scrolled off screen

Using Xcode 6 beta 6, I have used a standard View Controller and placed a Collection view into it. Following this, I have added a prototype cell from which an array on the CollectionViewController.m file provides the images.
While the images do appear, they do not load until after that cell has been scrolled off the screen and then back on. This is stopping any images from loading when the app opens until the user scrolls down.
The images are stored locally in the file, not a Database.
Despite the lack of images, I have linked the cells to another view controller, and even though no image is displayed, the segue still operates.
Thanks for any help in advance.
I guess you are setting the UIImage on the cell image view out of the main thread. Wrap the setter code into a following snippet:
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
cell.imageView.image = {UIImage object you've got};
}];
Optionally you could also try different, single-line replacement approach, if possible:
[cell.imageView performSelectorOnMainThread:#selector(setImage:) withObject:{UIImage object} waitUntilDone:NO];
I can't find what kind of cell you mean in fact; in every case, apply the same on a particular target image view, no matter if it's a part of your cell as a property or not.
you should use willDisplayCell method to assign image.
first initial image then create cell.
here is the code :
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
return cell;}
-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
imageView.image = images[indexPath.row];}
And don't forget to reload collection view after your data is ready to be loaded:
[_myCollection reloadData];

Showing a specific cell each scroll back on UICollectionView

I'm trying to load a custom cell each time someone scrolls up/back on my UICollectionView then if a condition is met, allow that user to see the previous items in the UICollectionView / resume normal UICollectionView behavior.
I tried subtracting the current indexpath.row, but that isn't working and I can't wrap my head around what exactly the case needs to be to make it work.
I was able to successfully get the custom cell to render as the third item (2) in the UICollectionView (shown below), but can't figure out how to make it's index path 0 and start the collection view on index path 1.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 2) {
MyCustomCell *customCell = [collectionView dequeueReusableCellWithReuseIdentifier:#"customCell" forIndexPath:indexPath];
return customCell;
}
else {
PhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"photo" forIndexPath:indexPath];
_obj_IndexPath = indexPath;
NSLog(#"%ld",(long)_obj_IndexPath.row);
_imageView = (UIImageView *)[cell viewWithTag:200];
_imageView.image = [UIImage imageNamed:[_imageArray objectAtIndex:indexPath.row]];
return cell;
}
}
The goal is a normal UICollectionView functionality with "full-screen" cells that scroll vertically AND during a certain condition scrolling to the previous cell is limited to only one scroll back AND that cell has a special / custom view on top of the cell content.
Any help or ideas would be awesome. Thank you!
I've updated my current code per comments below

How to save state of UICollectionViewCell

Please help me, how can I save state of UICollectionViewCell. For example: I have cells with UIWebView and when I dequeueReusableCellWithReuseIdentifier:forIndexPath: returned wrong cell, not for this indexPath and after it UIWebView content will reloaded for correct indexPath with twitches. Thanks!
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NewsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"NEWS_CELL" forIndexPath:indexPath];
if (!cell.isShowed) { // I just added boolean property
cell.isShowed = YES;
/*** some init actions ***/
}
return cell;
}
If I use this method, cells with cell.isShowed == YES return on wrong indexPath. But if I not use cell.isShowed content of UIWebView will reloaded in every showing cell
Sorry for my english :)
See what Apple's UIWebView Class Reference say:
Important: You should not embed UIWebView or UITableView objects in
UIScrollView objects. If you do so, unexpected behavior can result
because touch events for the two objects can be mixed up and wrongly
handled.
But UICollectionView inherits from UIScrollView. So you need to redesign your architecture.

UICollectionView cellForItemAtIndexPath not registering cell

I am trying to use UICollectionViewCell, since all I want to display is an image. I can add the image to the cell using UIColor colorWithImage: on the UICollectionViewCell's contentView property.
In my loadView method, I am registering the cell as follows:
[self.collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:#"MyCell"];
Below is my cellForItemAtIndexPath method:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"MyCell" forIndexPath:indexPath];
// cell customization
return cell;
}
When I run it, as soon as it hits the dequeue line, it crashes with the following error:
*** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:]
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'could not dequeue a view of kind: UICollectionElementKindCell with identifier MyCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
I tired setting up a custom cell, and used it as the class and I got the same error. My custom cell subclassed UICollectionViewCell and had nothing implemented, except for the default initWithFrame. That is because I wanted to just change the background colour of the view. I am not sure what the problem is but could someone please take a look at my code and help me? I've been trying to figure this out for quite a while with absolutely no luck at all.
If you just want to display an image, you don't need to do any subclassing, you can set the cell's backgroundColor with colorWithPatternImage:. Register the class like this:
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"Cell"];
Then use it like so:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithPatternImage:[self.results objectAtIndex:indexPath.row]];
return cell;
}
In this example, results is an array of UIImages.
If you are using xib in applivation then add following in your viewdidLoad method
[self.myCollectionView registerNib:[UINib nibWithNibName:#"CollectionViewCell" bundle:nil] forCellWithReuseIdentifier:#"CellIdentifier"];
otherwise If you using storyboard add following
[self.myCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"CellIdentifier"];
Finally add this (If not)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CellIdentifier" forIndexPath:indexPath];
return cell;
}
Hope above will help.
Try setting a breakpoint on
[self.collectionView registerClass:[ImageCell class] forCellWithReuseIdentifier:#"MyCell"];
I would guess your loadView (did you mean viewDidLoad?) method is not being called, so the class is never registered with the collectionView.
if your collection view is connected on storyboard and the delegate and datasource is set there, and you provide the necessary methods for the datasource and delegate, then adding the register call makes the
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath
return a UICollectionView instead of your own subclass of it. So do either but not both.
set your cell identifier name as in code