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.
Related
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.
I am trying to add a header to a collection view. I am using a custom layout that scrolls horizontally, it is used to view a list of avatar images for friends. I can get the header to appear but it does NOT dequeue. As soon as the header view goes off screen, its gone for good. Can anyone figure out why this is?
Thank you!
Collection View data source:
- (UICollectionReusableView *)collectionView:(SWAvatarViewerCollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath
{
if (self.showAddAvatarHeaderView && [kind isEqualToString:UICollectionElementKindSectionHeader]) {
return [collectionView dequeueAddAvatarViewHeaderForIndexPath:indexPath];
}
return nil;
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(SWAvatarViewerCollectionViewFlowLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
if (!self.showAddAvatarHeaderView) {
return CGSizeZero;
}
return CGSizeMake(kSWAvatarViewerAddAvatarHeaderViewWidth, CGRectGetHeight(collectionView.bounds));
}
Avatar collection view:
- (SWAvatarViewerAddAvatarHeaderView *)dequeueAddAvatarViewHeaderForIndexPath:(NSIndexPath *)indexPath {
SWAvatarViewerAddAvatarHeaderView *headerView = [super dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
withReuseIdentifier:[SWAvatarViewerAddAvatarHeaderView headerReuseIdentifier]
forIndexPath:indexPath];
headerView.delegate = self;
return headerView;
}
Nib file registration:
[self registerNib:[SWAvatarViewerAddAvatarHeaderView nib]
forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
withReuseIdentifier:[SWAvatarViewerAddAvatarHeaderView headerReuseIdentifier]];
Layout:
#pragma mark - Initialization
- (void)configureFlowLayout {
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// Padding for cells is taken into account in the cell's layout. Remove all
// padding between cells
self.sectionInset = UIEdgeInsetsMake(0, 00.0f, 0, 00.0f);
self.minimumLineSpacing = 0.0f;
self.minimumInteritemSpacing = CGFLOAT_MAX;
_cellBottomLabelFont = [UIFont systemFontOfSize:12.0];
CGSize defaultAvatarSize = CGSizeMake(44.0f, 44.0f);
_avatarViewSize = defaultAvatarSize;
_springinessEnabled = YES;
_springResistanceFactor = 1000;
}
You're apparently using a third-party layout I've never heard of. After some discussion with you, my feeling is that my first comment under your question was probably right: the layout itself may be buggy.
In a collection view, the layout attributes of the cells (position, size, transform, alpha, etc.) are the responsibility of the layout. So if something disappears merely because it is scrolled off the screen and then back on, it sounds like the layout itself is not doing its job correctly.
Quick googleing did not unveil the SWAvatarViewerCollectionViewFlowLayout. If you have the sources, you can take a look at the layout code, there should be a method called layoutAttributesForElementsInRect:.
The collection view is dequeuing items as soon as they go offscreen which is determined with the help of the aforementioned method (The layout attributes contain the views center and dimensions). If the method returns always the layout attributes for the header it will not get dequeued.
However if you do not have access to the code (like a static lib) you probably can not do much about it.
Just put this method that will solve all the problems
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(-50, 10, 10, 10); //asuming
//UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)
}
Enjoy.
In my UICollectionView I have a cell that should take the entire width of the device. Here is how I set the size for the item:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.view.bounds.size.width, 120);
}
I have found that on rotation, the width of the cell does not change. I can resolve this using [collectionView.collectionViewLayout invalidateLayout] in didRotateFromInterfaceOrientation: but this isn't satisfactory. What if the user rotates while in another screen in my app? I will need to add the same to viewWillAppear. What about if the rotation occurs while the app is backgrounded? Now I need to add it for the UIApplicationDidBecomeActiveNotification notification.
What confuses me most is that this is not required for my custom headers in the same collection view. The following supplementary views correctly re-size on orientation change:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(self.view.bounds.size.width, 40);
}
Where am I going wrong? What should I do to have the cells re-size automatically to fill the width of the collection view?
A bit late I know but could you solve this by subclassing flow layout and adding?
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return TRUE;
}
Currently I have a 9 items displayed in my collection. I want a 3*3 grid for each section I have. So when I want to go to the next section I scroll to the right and and I see the 3*3 grid for my next section. What I did to accomplish this was setting the height of the UICollection to 3*height_of_my_cell. I also made sure that:
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0f;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0f;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0);
}
So the goal is really to have the cells pasted to each other (no space between them). The problem is that what I am getting is this:
To see the 7,8 and 9 I need to scroll to the right. So I see that I am able to get rid of the space between the "columns" but not the rows. So do I need o create a custom UICollectionViewFlowLayout to achieve this? Also this is being done on iOS7, which I am not sure if it might influence the final result.
Just set the property of UICollectionViewFlowLayout, such as:
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 0;
Was able to solve the issue, by creating a custom UICollectionViewFlowLayout and adding this line:
[self setSectionInset:UIEdgeInsetsMake(-65.0f, 1.0f, 0.0f, 0.0f)];
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.