I am implementing a Table for iPad and facing some major problems.
For the GridView I implemented my own subclass of UITableViewCell which works fine.
The data is shown correctly, but I have a problem when I want to access a single cell to go to some new detail view. Since one row only contains one cell, the didSelectRowAtIndexPath only gives me access to the complete cell, but I don't know which column the single cell is in.
Then I implemented a TapGestureRecognizer. This shows me the row and column and works, but only until I start scrolling... the column part still works, but the row is shown incorrect since the TapRecognizer overlaps the didSelectRowAtIndexPath (bad but not so important side effect.. there is no blue highlighting of the selected row).
Is there a way to find out how many pixels I scrolled? Or is there an even better solution?
I highly recommend using UICollectionView over those 3rd party classes. There are quite a few advantages to having access to all of the delegate protocols (like showing the cut copy paste UIMenuController on a long press without a UIGestureRecognizer, for example) I use one myself as a grid.
To acheive a grid layout, I did the following...
1) I set the following Delegates in my .h file:
#interface YourViewControllerWithCollectionView : UIViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> {
}
#property (nonatomic, retain) IBOutlet UICollectionView *myCollectionView;
#end
Notice, that I did not set the UICollectionViewDelegate because UICollectionViewDelegateFlowLayout is actually a sub-protocol of UICollectionViewDelegate, so there is no need to set both.
2) In the .m file, synthesize the collection view, and in viewDidLoad declare the datasource and delegates: (don't forget to connect your outlets, and you might want to put a background color on the cell so you can see it)
#synthesize myCollectionView;
viewdidLoad:
- (void)viewDidLoad
{
self.myCollectionView.delegate = self;
self.myCollectionView.dataSource = self;
//...
}
3) Implement the datasource
#pragma mark - UICollectionView Datasource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
//the number of cells you want per row
return 4;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
//load sublassed UICollectionViewCell called MyCollectionViewCell
static NSString *cellIdentifier = #"cell";
MyCustomCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.title.text = #"Title"
// customize the cell...
return cell;
}
5) Implement the UICollectionViewDelegateFlowLayout
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
//this is what forces the collectionview to only display 4 cells for both orientations. Changing the "-80" will adjust the horizontal space between the cells.
CGSize retval = CGSizeMake((myCollectionView.frame.size.width - 80) / 4, 78);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
// for the entire section, which we have set to 1, adjust the space at
// (top, left, bottom, right)
// keep in mind if you change this, you will need to adjust the retVal
// in the method above
return UIEdgeInsetsMake(5, 20, 10, 20);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
CGFloat interimSpacing = 0.0f;
return interimSpacing;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
CGFloat lineSpacing = 0.0f;
return lineSpacing;
}
6) Last, but certainly not least, invalidate the layout on orientation change to redraw the cells:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration{
[self.myCollectionView.collectionViewLayout invalidateLayout];
}
And because you implemented UICollectionViewDelegateFlowLayout, you already have access to UICollectionViewDelegate to handle selection, etc. like:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
//do something when a cell is tapped...
}
More information can be found here: http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12
Look at AQGridView or some of the other controls at CocoaControls.com.
I recommend AGAINST UICollectionView. UICollectionView is easy to use, but not stable enough at this moment. I am using GMGridView for my apps. After a few months operations, I can say that it is stable enough for the production release. Another alternative is PSTCollectionView, which is a 100% API compatible replacement for UICollectionView. However, it is unfinished and contains even more bugs than UICollectionView.
The disturbing issues I have with PSTCollectionView are:
poor performance if you want to display > 80 cells on screen
reloading sections is not implemented
decoration views are not implemented
The disturbing issues I have with UICollectionView are:
the items in the first column may disappear
inserting the first cell will crash
reloading sections with header view will crash
blurry text in cells
Check open radar
https://openradar.appspot.com/search?query=UICollectionView
for all current issues with UICollectionView.
I believe UICollectionView and PSTCollectionView will be good choices when they are stable. But at this moment, GMGridView is a better choice.
Related
I've got a UICollectionView, and have a custom UICollectionTableViewCell with a UIImageViewInside.
I've got the spacings as followed:
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// TODO: Select Item
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Deselect item
}
#pragma mark – UICollectionViewDelegateFlowLayout
- (UICollectionViewFlowLayout *)collectionViewFlowLayout
{
UICollectionViewFlowLayout *flowLayout = [UICollectionViewFlowLayout new];
flowLayout.sectionInset = UIEdgeInsetsZero;
flowLayout.minimumInteritemSpacing = 0.0f;
flowLayout.minimumLineSpacing = 0.0f;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
return flowLayout;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat widthOfTheScreen =self.view.frame.size.width;
CGSize retval = CGSizeMake(widthOfTheScreen , widthOfTheScreen *1.5);
return retval;
}
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsZero;
}
Now, when I run it, it works perfectly for my purpose. It shows the image in the centre of the view (I've got my collectionview under a label), and it shows it almost exactly how I wanted it (don't worry about the shortage of bottom space bit).
The image below shows the first item (without scrolling):
However, when I scroll right, I start to get slight gaps. Also, this gap gets bigger with every scroll (I have the background red so you can see).
This is the first scroll:
This is the second scroll:
And this is the third scroll:
And so on goes the pattern. I've got a feeling that it's something to do with the insets, but not sure how to remove it.
OR is it something to do with some outset? I've never heard of such, but that could also be the problem
Thanks a lot in advance for your advice.
Right off the bat, your UI feels and looks pretty strange. I certainly hope the imageview is not nested inside another scrollview inside the collection view. If you care to put the project up we can run it to see what the issue is.
In my project i have collection ,in which horizontal pagination is enabled, Every thing working fine but, when i scroll,particular cell item not fit entire cell,It show half image of previous cell item and half current Items, i need One item to fit the entire screen ??? Any suggestion are welcome
Here is the code:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath; {
SingleItemCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"SingleItemCollectionViewCell" forIndexPath:indexPath];
[cell ConfigaureCollectionViewItem:self.totalCellItems[indexPath.row]]; return cell;
}
-(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = CGSizeMake(self.bounds.size.width - 20, self.bounds.size.height - 40);
return size;
}
Perhaps you should be using UIPageViewController in stead of UICollectionView. From your question it seems that you are trying to mimic the behaviour of the former.
So I have been have some issues with UICollectionView which seems to be a common theme on the internet. Here, Here and Here. I have tried the links suggestions. So just some context.
1.) I'm pulling data from Parse.com (no issue there)
2.) The results are looped over and populated in an array to then fill out the cell. (just like a UITableView)
3.) The data is text based only and populates accordingly, no images to deal with at the moment ;-).
The issue seems to be when I render the dataset. I have set the line spacing between each row to be the following;
//reduce each section to 1px so that it looks like a record set.
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 1.0;
}
//reduce each section to 1px so that it looks like a record set.
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 1.0;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *) collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
//UIEdgeInsetsMake(top, left, bottom, right);
return UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
}
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
This works accordingly. AFTER you scroll (see below screenshots)
Wrong Render
Correct Render
Cell Code
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"cell";
PatternCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
PFObject *cellObject = [flightRecordData objectAtIndex:indexPath.row];
/* ALL THE UILABEL ELEMENTS ARE SET HERE JUST REMOVED TO SAVE SPACE */
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
[cell.layer setNeedsDisplay];
return cell;
}
I'm happy to deal with the rendering issue because apart from that it works. However, my OCD is kicking in and its doing my head in trying to work out what the issue is. I have even deployed to the device to see if its a simulator issue which its not. Each of the suggested posts from others I have tried but didn't seem to work.
Any ideas on how to fix this? I'm new to iOS so be gentle :-P.
UPDATE:
Thanks for the feedback, below is the class and screen shots of the storyboard. I'm using the custom class just as an object that I call when required.
Custom UICollectionViewCell Class
#interface PatternCollectionViewCell : UICollectionViewCell {
IBOutlet UILabel *pilotNameLabel;
IBOutlet UILabel *pilotTotalHoursLabel;
//etc etc...
}
#property (nonatomic,strong) IBOutlet UILabel *pilotNameLabel;
#property (nonatomic,strong) IBOutlet UILabel *pilotTotalHoursLabel;
Storyboard
CollectionView
CollectionViewCell
CustomCell
You had a mismatch between the item size given in the flow layout (configured on the collection view in Interface Builder), which gave the height as 58 pixels high, and the size of the custom cell, which had a height of only 52 pixels.
This explains the extra spacing around the cell.
I'm new to IOS Development,
I'm designing an interface where I want to use the collection view to place the controls as if in a grid,
For this, I'm using a collection as shown in the picture below
However, at runtime, this screen is appearing completely black:
I was expecting to see the interface I designed as in the first image. But why is the interface appearing completely black?
The default color of UIcollectionView will looks like black only if you want make it visible try to change the View color of UicollectionView and you want to make visible your grid Layout means connect your collection view with delegate and datasource and use collection view delegate functions.
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 10;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
return cell;
}
and this is good tutorial for Uicollection view Look at this link
http://postimg.org/image/6bws3catp/
As you can see on the image I need something that gives me the possibility of resizing a cell depending on the length of the text that contains.
I' ve been trying to do that with a UICollectionview but the cells have always the same size and if I try to alterate the size playing with the frame.size and location parameters the scroll gets crazy.
Maybe the UICollectionView isn't the best choice...
Thank you very much
EDIT:
Because of your answers my cells are able to change dynamically their size but the margins aren't behaving as I expected.
The margins of the cells depends always on the biggest cell of the same row
http://postimg.org/image/3scthf9rv/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 6;
}
I have implement this to set my margin value between cells in 6 points, but maybe this only works when you have one cell in each row in a vertical collection view..
Thank you again for all your help
You can check out https://github.com/bryceredd/RFQuiltLayout . Looks
like something you can use for this...
you can override the following method and return a CGSize object that specifies the size you want to use for each cell. Using this method, you can actually have each cell be a different size:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
Example:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(100, 100);
}
Your view controller needs to be a delegate of UICollectionViewDelegateFlowLayout in order for this method to be called. So don't forget to add that delegate declaration to your view controller's .h file, such as:
#interface MyViewController () <UICollectionViewDelegateFlowLayout>
UICollectionView is the correct choice. You just need to customise the flow layout attributes.
Read Customizing the Flow Layout Attributes
Specifically you would need to implement Collection View Delegate method:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// In this method you can calculate the size of the string for each cell
UIFont *font = // font to create the text for each cell
NSString *string = // text string for each cell
CGSize size = [string sizeWithFont];
return size;
}