A UICollectionViewLayout that uses supplemental views to display a folder below a cell that looks like the screen was split. Mimics the pre iOS7 springboard groups visualization. Wrote this because all of the other "folder" controls like this use a screen shot to do the splitting, but I wanted my collection view to still be functional even with the folder open.
Poor quality gif, but you get the idea.
Data provided by Marvel. © 2014 Marvel
- Copy RBCollectionViewInfoFolderLayout .h/.m into your project
- Set the layout on your collectionView to Custom, and set it's name to RBCollectionViewInfoFolderLayout
- Grab the layout in viewDidLoad and setup your collectionView (Note: currently you have to register a RBCollectionViewInfoFolderDimpleKind)
- Implement the delegate methods
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(RBCollectionViewInfoFolderLayout *)collectionViewLayout heightForFolderAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(RBCollectionViewInfoFolderLayout *)collectionViewLayout sizeForHeaderInSection:(NSInteger)section;
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(RBCollectionViewInfoFolderLayout *)collectionViewLayout sizeForFooterInSection:(NSInteger)section;
Setup layout
- (void)viewDidLoad
{
[super viewDidLoad];
RBCollectionViewInfoFolderLayout * layout = (id)self.collectionView.collectionViewLayout;
layout.cellSize = CGSizeMake(216, 325);
layout.interItemSpacingY = 10;
layout.stickyHeaders = YES;
[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:RBCollectionViewInfoFolderHeaderKind withReuseIdentifier:@"header"];
[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:RBCollectionViewInfoFolderFooterKind withReuseIdentifier:@"footer"];
[self.collectionView registerClass:[ComicDataView class] forSupplementaryViewOfKind:RBCollectionViewInfoFolderFolderKind withReuseIdentifier:@"folder"];
[self.collectionView registerClass:[RBCollectionViewInfoFolderDimple class] forSupplementaryViewOfKind:RBCollectionViewInfoFolderDimpleKind withReuseIdentifier:@"dimple"];
}
Handle various suplementary view request
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView * reuseView;
if (kind == RBCollectionViewInfoFolderHeaderKind)
{
reuseView = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
// Nothing new here, you've done it before
}
if (kind == RBCollectionViewInfoFolderFooterKind)
{
reuseView = [self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"footer" forIndexPath:indexPath];
// Nothing new here, you've done it before
}
// Example from our demo showing the use of a custom UICollectionReusableView
if (kind == RBCollectionViewInfoFolderFolderKind)
{
ComicDataView * comicDataView = (id)[self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"folder" forIndexPath:indexPath];
comicDataView.backgroundColor = [UIColor colorWithRed:0x88/255.0 green:0xc2/255.0 blue:0xc4/255.0 alpha:1.0];
UILabel * label = (id)[reuseView viewWithTag:1];
if (label == nil)
{
label = [[UILabel alloc] init];
label.tag = 1;
label.frame = CGRectMake(0, 0, reuseView.frame.size.width, reuseView.frame.size.height);
label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
label.textAlignment = NSTextAlignmentCenter;
[reuseView addSubview:label];
}
comicDataView.title.text = self.data[self.dataKeys[indexPath.section]][@"results"][indexPath.row][@"title"];
comicDataView.desc.text = self.data[self.dataKeys[indexPath.section]][@"results"][indexPath.row][@"description"];
comicDataView.upc.text = self.data[self.dataKeys[indexPath.section]][@"results"][indexPath.row][@"upc"];
reuseView = comicDataView;
}
// Example of how to color the dimple to match your folder
if (kind == RBCollectionViewInfoFolderDimpleKind)
{
RBCollectionViewInfoFolderDimple * dimple = (id)[self.collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"dimple" forIndexPath:indexPath];
dimple.color = [UIColor colorWithRed:0x88/255.0 green:0xc2/255.0 blue:0xc4/255.0 alpha:1.0];
reuseView = dimple;
}
return reuseView;
}
- Imlement decoration view that places a caret over opened item linking it to the folder
- Animate dimple decoration
- Make header/footer/dimple optional
- Figure out why position of the folder animates open, but the view just pops in
- Implement sticky headers
- Refactor deltaX calculation into prepareLayout so it isn't re-done for every item
- Allow for per item folder heights.
- Implement delegate methods to allow per-section headers/footers
- Add SectionInset property/delegate
- Add ability to get item from a point in the displayed folder view.