I am stuck in frame of uicollectionview cell frame
what I want to do is,
in landscape mode of iPad I want to show 3 cells,
and in portrait 2 cells.
when I write the code of frame in method - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
its not affecting the size of frame.
I checked by applying debugger whether its coming in this method or not.
but its coming and returning the size.
by default I have to launch my application in landscape and then if required in portrait.
Here is how its showing in landscape
Here how this cells looking in portrait
Here is my code for frame
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//return [self.cellSizes[indexPath.item] CGSizeValue];
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
{
return CGSizeMake(100, 100);
}
return CGSizeMake(200, 200);
}
What ever value I pass, frame is not at all changing.
I didn't passed any other frame value any where.
I want to give hardcoded value to cell frame first then will go for dynamic.
but I'm stuck at the first place only.
Can any one please help me.
Thanks in advance.
i faced similiar problem so basically you should implement UICollectionViewDelegateFlowLayout in your view controller otherwise design a custom collectionviewcell and register in your view controller , it will definitely work . Try it .
in my case
i added xib by subclassing UICollectionViewCell and designed it accordingly and it works so you may try .
For dynamic collection view cell you can use collection view methods like this.
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section{
return [_elements count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"cell";
MosaicCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
MosaicData *data = [_elements objectAtIndex:indexPath.row];
cell.mosaicData = data;
float randomWhite = (arc4random() % 40 + 10) / 255.0;
cell.backgroundColor = [UIColor colorWithWhite:randomWhite alpha:1];
return cell;
}
For details you can see this example. This is an perfect example of your need
https://github.com/betzerra/MosaicLayout
You need to reload the collection view when orientation will get change. so the CGRect size method will be called for the cell to recreate cell.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
// do something after rotation
[_collectView reloadData];
}
Add this method and reload your collection view so - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath will get called and size will get changed.
Thanks
Related
I've a strange behavior with UICollectionView.
In Figure 1 is shown the correct behavior when the user scroll up the collection: the items goes under header view.
[FIGURE 1]
When I reload Items after a search, some items goes over header during scroll.
I've no idea about the cause...
Any ideas or suggestions?
Thanks.
EDIT
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(CGRectGetWidth([UIScreen mainScreen].bounds), CGRectGetWidth([UIScreen mainScreen].bounds) * 0.612f);
}
What worked for me is to call reloadData() instead of trying to reload with animation (reloadSections()).
In my case, I had a show/hide button to toggle the number of rows in section between item count and 0 (expand the content of the section).
When I replaced
collectionView?.reloadSections([section])
with
collectionView?.reloadData()
I no longer had the issue.
My working code for UICollectionView along with HeaderView inside UIViewController:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 20;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor blueColor];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100, 100);
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"header" forIndexPath:indexPath];
return view;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(self.view.frame.size.width, 100);
}
Storyboard:
Output:
Please check this. Hope this will help you in some other way.
You can try to set sectionHeadersPinToVisibleBounds = true property on your UICollectionViewFlowLayout. Because every UICollectionView has own layout.
Apple doc
A Boolean value indicating whether headers pin to the top of the collection view bounds during scrolling.
Maybe it will help. Add this code into viewDidLoad.
(self.yourCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).sectionHeadersPinToVisibleBounds = true
After trying many solutions in my case that works,
collectionView.clipsToBounds = true
In my collection view I want to scale the collection view cell that is selected. Along with that I also want to maintain same interItemSpacing between cells before the selection and after the selection, including enlarged cell. But if I just scale the cell by setting cell.transform property scaled cell overlaps on the neighbor cell.Other cells should adjust themselves to maintain the space. How do I solve this ?
i.e,
cell -50pix- cell -50pix- cell
cell -50pix- scaled cell -50pix- cell
By applying a transform, you are just scaling the view up in size. To adjust the size and allow the rest of the UICollectionView to adjust you will need to return a new size in sizeForItemAtIndexPath:
When the item is selected, you should reload that item at that indexPath using:
[collectionView reloadItemAtIndexPath:selectedIndexPath]
Replace selectedIndexPath with name of your variable storing the selected indexPath.
You don't want to invalidateLayout because you're just changing the appearance of one item.
I don't know whether this is the best solution,
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionViewCell *cell = (CollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
if ([indexPath isEqual:selectedIndexPath]) {
return CGSizeMake(175, 175); // return enlarged size if selected cell
}
return CGSizeMake(150, 150);
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
selectedIndexPath = indexPath; // set selected indexPath
[collectionView performBatchUpdates:^{
[collectionView.collectionViewLayout invalidateLayout];
} completion:^(BOOL finished) {
}];
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0,0, 0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 20;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 20;
}
I'm using a collection view inside of a static table view cell and I'm using autolayout to define the collection view's frame. Also, I'm using FlowLayout as the collectionViewLayout.
The problem:
The behaviour is just as expected for the iPhone 4s and 5 screen. (same width)
Once the width changes (iPhone 6 and 6 Plus), the collection view resizes properly, but the content keeps it size.
This happens both for the cells and for the sections.
Extra info:
I'm setting collectionViewLayout minimumInteritemSpacingForSectionAtIndex to zero.
The width of the cells is always being set to tableView.frame.size.width / 2
Where I configure the layout:
CGFloat headerHeight = 52;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
collectionViewLayout.headerReferenceSize = CGSizeMake(self.width, headerHeight);
This is what it looks now. The green part represents the UICollectionView. Black and blue the cells. The dividing lines should be resizing and the cells should be divided in 2 columns.
From the code you posted, you are just setting the size for the header but I suppose you also have something like
collectionViewLayout.itemSize = CGSizeMake(self.collectionView.frame.width/2, height);
The important part is in which method you configure this, because if you do it in viewDidLoad the views are not correctly layouted yet so the width would just be the one set in the storyboard, no matter on which device you run your app.
The solution would be to place the code above in viewWillLayoutSubviews
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
collectionViewLayout.itemSize = CGSizeMake(self.collectionView.frame.width/2, height);
collectionViewLayout.headerReferenceSize = CGSizeMake(self.collectionView.frame.width/2, height);
}
Another way would be to implement the flowLayout delegate method:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return cCGSizeMake(collectionView.frame.width/2, CUSTOM_HEIGHT);
}
// The same for the header
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
return cCGSizeMake(collectionView.frame.width/2, CUSTOM_HEIGHT);
}
Make sure you set the delegate for the collectionView
Let me know how it goes :)
Update
For the cells, add these methods too:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return CGRectZero;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0;
}
As for the sectionHeader, maybe you need to check the constraints you have there, for the separator for example.
Be sure to use all the following for precise styling:
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
To change the cell content size, use this:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake((kScreenWidth/2-8), 44); // Use your own X and Y sizes
}
i want to change the size of cells in a uicollectionview with a slider but i cant find how to do.
its like in the macOs finder when you see icons, you can change the size of it with a slider.
I want it for an iPad app
- (IBAction)sliderChanged:(id)sender {
[self.tableView reloadData];
}
Hook up your slider to the above method (for value changed), then use the following method to define the height:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath {
return self.slider.value;
}
Nearly perfect, i want for a uicollection view so i need to change with:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//Return the size of each cell to draw
CGSize cellSize = (CGSize) { .width = 320, .height = self.slider.value};
return cellSize;
}
I am attempting to lay my UICollectionView out such that it is a 2x3 grid per page. Here is what I am getting so far:
As you can see, the next "page" is peeping in from the right, which I don't want. I figured if I know my width is always going to be 320pts (iPhone only), then I would want my cells to be 130pts in width with 15pts on either side.
Code for layout delegate:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(130, 130);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(20.0f, 15.0f, 20.0f, 15.0f);
}
And also cellForItemAtIndexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CustCollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:kReuseID
forIndexPath:indexPath];
//Set up list name label
cell.LblListName.font = [self getDefaultFontWithSize:15.0f];
cell.LblListName.textColor = fontAndTertiaryColor;
cell.LblListName.textAlignment = NSTextAlignmentCenter;
cell.LblListName.text = #"Failtron";
//cell.LblListName.adjustsFontSizeToFitWidth = YES;
cell.backgroundColor = secondaryColor;
cell.parallaxIntensity = kParallaxMotion;
[Utilities createViewBorder:cell];
return cell;
}
I thought an inset would act like padding in CSS but I believe I'm off the mark with that one, I should also note that in the UIStoryboard my layout is set to flow. Please let me know if I am missing any relevant code, this is my first attempt with a UICollectionView. I would like this to scroll horizontally as well.
Ok, there are tons of ways to manipulate layouts for a UICollectionView, but sounds like since you are using "flow" you can just implement <UICollectionViewDelegateFlowLayout> in your .h and then use the following methods to tweak your layout to your liking:
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
// Size of the cell
CGSize retval = CGSizeMake(130,130);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
//top, left, bottom, right
return UIEdgeInsetsMake(0, 20, 0, 20);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
//Minimum spacing between cells
CGFloat interimSpacing = 0.0f;
return interimSpacing;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section {
// Minimum spacing between lines. In your case,
this is the distance between columns
// If your scroll direction was vertical,
this would be the distance between rows
CGFloat lineSpacing = 20.0f;
return lineSpacing;
}
I've prepopulated this code with some values that should be pretty darn close to what you wanted to accomplish.
Alternatively, all of this can be done in Interface Builder by selecting the UICollectionView and adjusting the values in the Size Inspector, albeit more confusing in my opinion.