In my uicollectionview delegate, i have this code. Basically it is to set the size of the cells based on the colectionview size.
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat ratio = 200.0/280.0; // w/h
CGFloat cellWidth = (collectionView.frame.size.width-50)/4.0;
CGFloat cellHeight = cellWidth / ratio;
CGSize cellSize = CGSizeMake(cellWidth, cellHeight);
return cellSize;
}
How can I force this delegate to run after I change the collectionView frame without reloading the collectionView? One way I think of is manually calling this funtion by looping through all visible cells, but seems way too heavy for something so simple.
HELLLPPPPPP
You can call this delegate manually like this :
CGSize size = [self collectionView:self.collectionView
layout:self
sizeForItemAtIndexPath:indexPath];
Ok I found the solution by myself. In order to force this delegate to run again after resizing collectionview, we just need to reload a SINGLE cell. For example, the first cell. Then collectionview will resize all cells automatically.
NSIndexPath *firstItem = [NSIndexPath indexPathForRow:0 inSection:0];
[_cardCollectionView performBatchUpdates:^{
[_cardCollectionView reloadItemsAtIndexPaths:#[firstItem]];
} completion:^(BOOL finished) {}];
Anyway thanks all for trying to help me.
Related
Guys I need your help ... I created a custom control segment through an UICollectionView ..
CustomView.m
I have 5 cells that contain a label with the title of the cell
To get the cell width by the width of the UILabel I implemented the sizeForItemAtIndexPath method in this way:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = [[[self titleSection] objectAtIndex:indexPath.item] sizeWithAttributes:nil];
return CGSizeMake(size.width +35 , self.frame.size.height);
}
I also created a UIView that has the cursor function that indicates which cell has been selected.
To animate the cursor (UIView) I implemented this way:
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:indexPath.item inSection:0];
[collectionView scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
UDPassData *data = [UDPassData sharedInstance];
[data.sectionContentCollection scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
if (indexPath == newIndexPath) {
[collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
UICollectionViewLayoutAttributes *attributes = [collectionView layoutAttributesForItemAtIndexPath:newIndexPath];
CGRect cellFrameInSuperview = [collectionView convertRect:attributes.frame toView:collectionView];
data.index = cellFrameInSuperview;
[UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
_horizontalBar.frame = CGRectMake(cellFrameInSuperview.origin.x, _horizontalBar.frame.origin.y, cellFrameInSuperview.size.width , 3);
} completion:nil];
}
UICollectionViewController.m
now in another ViewController i have another UICollectionView with horizontal scrolling that shares the index path with the segment control so that I can control the scrolling of the collectionView even with the custom segment control .. To here everything works and I managed to get everything but I just have a problem ..
The segment control slider does not move when uicollection view scrolls ... In short, if the collectionView is in cell two, the custom segment control cursor should move to the second cell in the segment control I created .. I hope to to be able to explain
EDIT : What I'm trying to get is this I've seen from the Youtube application. The top menu ...
I'm doing this with 2 collectionView.
the first collectionView is the menu (built into a UIView custom class)
the second collectionView is browsing between pages and is located in an external UIViewController
Make sure to reload collectionView Data Source in order to fresh it.
[self.collection1 performBatchUpdates:^{
[collectionView reloadData]
} completion:nil];
I have UICollectionView inside UITableViewCell, cells are of dynamic width depending upon text.The problem I am facing is when i scroll the TableView after that collection inside cell is appearing correct.
Here is what I did, I called reloadData after datasource is set and also called invalidateLayout but not working
Here is what I did,
Inside tableViewCell class,
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize calCulateSizze =[[datasource objectAtIndex:indexPath.row] sizeWithAttributes:NULL];
NSLog(#"%f %f",calCulateSizze.height, calCulateSizze.width);
calCulateSizze.width = calCulateSizze.width+20;
calCulateSizze.height = 35;
return calCulateSizze;
}
#pragma mark - Public
- (void)setCellData:(id)pData {
GSHColumns *column = (GSHColumns*)pData;
if (column.options.count > 0) {
datasource = column.options;
[_collectionView reloadData];
[_collectionView.collectionViewLayout invalidateLayout];
}
[titleLabel setText:column.displayName];
}
Here is what it looks like before scrolling
and after scrolling,
I'm currently working on autosizing cells which are new in iOS8.
According to WWDC 2014 video 'What's New in Table and Collection Views', all that is required to autosize cells is to set an estimatedSize on the UICollectionViewFlowLayout given to the UICollectionView on initialisation, and override the sizeThatFits: method in the UICollectionViewCell.
Initialisation:
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setEstimatedItemSize:CGSizeMake(146.0f, 156.0f)];
_collectionView = [[UICollectionView alloc] initWithFrame:[_containerView bounds] collectionViewLayout:flowLayout];
sizeThatFits method in my cell, where _userLabel is the label that is on the bottom and marks the actual height.
- (CGSize)sizeThatFits:(CGSize)size
{
CGSize actualSize = CGSizeMake([[self contentView] bounds].size.width, [_userLabel frame].origin.x + [_userLabel bounds].size.height);
return actualSize;
}
It turns out that actual size has larger height than my estimated size, which should be okay and the cell actually gets resized properly in height.
Now with the iPhone6 and 6+, the width can also differ. I want the cells to properly span the width of the screen. I've therefore implemented three delegate methods on UICollectionViewFlowLayout; my first intuition is to calculate the width I want the cells to have according to the screen width, the section insets and the inter-item spacing.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
UIEdgeInsets sectionInsets = [self collectionView:collectionView layout:collectionViewLayout insetForSectionAtIndex:[indexPath section]];
CGFloat interItemSpacing = [(UICollectionViewFlowLayout *) collectionViewLayout minimumInteritemSpacing];
CGFloat cellWidth = ([_collectionView bounds].size.width - sectionInsets.left - sectionInsets.right - interItemSpacing) / 2;
CGSize collectionViewCellSize = CGSizeMake(cellWidth, 156.0f);
return collectionViewCellSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 12.0f;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f);
}
It works, however partly. The collectionView won't respect the top section inset, and when scrolling the collectionView, switching out another tab and then back again, cells seem to have disappeared.
Apparently I'm doing something wrong, but I can't seem to figure out where. Anyone got a clue?
I want to animate my collectionview cell so that when I touch it, a mapview slides out from underneath it and basically expands into the space, by pushing the cell underneath it down a little bit. I tried using this: UICollectionView: Animate cell size change on selection, but was unable to get it to work properly.
Here what I tried.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[((FeedCell *)[collectionView cellForItemAtIndexPath:indexPath]) setIsSelected:YES];
[collectionView.collectionViewLayout invalidateLayout];
__weak FeedCell *cell = (FeedCell *)[self.photoCollectionView cellForItemAtIndexPath:indexPath]; // Avoid retain cycles
void (^animateChangeWidth)() = ^()
{
CGRect frame = cell.frame;
frame.size = CGSizeMake(frame.size.width, 420);
cell.frame = frame;
};
// Animate
[UIView transitionWithView:[collectionView cellForItemAtIndexPath:indexPath] duration:0.5f options: UIViewAnimationOptionCurveLinear animations:animateChangeWidth completion:nil];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if(((FeedCell *)[self.photoCollectionView cellForItemAtIndexPath:indexPath]).isSelected == YES){
return CGSizeMake(320, 420);
}
return CGSizeMake(320, 320);
}
I have a custom CollectionView cell and it has a property for isSelected. I'm not sure what I should do for the xib of the cell (whether to put the map view in there, have the CGSize be the selected size or deselected size, etc.) Any help would really be appreciated!
I am trying to do the same thing as you and found your question in my search. It appears that you have a pretty good solution (at least in my inexperienced opinion). What isn't working for you? I got it to do what I wanted by copying your code almost verbatim. I changed a few things, but didn't test the code before making the changes. Here is what I have that works for me in my didSelectItemAtIndexPath method:
__weak MyCell *cell = (MyCell*)[collectionView cellForItemAtIndexPath:indexPath];
[cell setSelected:YES];
[collectionView.collectionViewLayout invalidateLayout];
void (^animateChangeWidth)() = ^()
{
CGRect frame = cell.frame;
frame.size = CGSizeMake(frame.size.width, 340.0f);
cell.frame = frame;
};
// Animate
[UIView transitionWithView:cell duration:0.5f options: UIViewAnimationOptionCurveEaseInOut animations:animateChangeWidth completion:nil];
I also have overridden collectionView:layout:sizeForItemAtIndexPath so I assume that is working for you as well.
Sorry I can't be more specific. It would help if you said what about it wasn't working.
I have a UICollectionView which uses a waterfall style layout to show different sized cells. The height calculation for each cell works just fine.
The problem I have is that I have to change the size of two outlets (UIImage and UILabel) in each cell and I donĀ“t know where to change the frame size in order prevent the UICollectionView from animating said frame size change. I tried it to do in the layoutSubviews method of each cell and in the cellForItemAtIndexPath without results. Every time the viewcontroller containing the UICollectionView appears the frame change for the two outlets in each cell is animated.
Example setting the frame for just the image inside cellForItemAtIndexPath:
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CVCNewspaper *cell = (CVCNewspaper *)[collectionView dequeueReusableCellWithReuseIdentifier:CELL_IDENTIFIER_NEWSPAPER forIndexPath:indexPath];
BONewspaper *newspaper = [newspapers objectAtIndex:indexPath.row];
CGFloat width = cell.frame.size.width;
// Calculate rect for imageView
CGFloat objectWidth = newspaper.coverNews.imageWidth ? newspaper.coverNews.imageWidth : 180;
CGFloat objectHeight = newspaper.coverNews.imageHeight ? newspaper.coverNews.imageHeight : 100;
CGFloat scaledHeight = floorf(objectHeight / (objectWidth / width));
cell.imageViewCover.frame = CGRectMake(MARGINVIEW, HEADERHEIGHT + 5, width, scaledHeight);
[cell fillCellWithNewspaper:newspaper];
return cell;
}