iOS UICollectionView special cell order - ios

I have a simple collection view with 5 elements.
The default order of the cells looks like this:
I wanna know if it's possible to change the padding\order of the cells to get result like this:

Option 1: (Clean option)
You should have 2 sections.
Section 1 with 3 cells
Section 2 with 2 cells
You can then adjust the inset with collection​View(_:​layout:​inset​For​Section​At:​) for the section you want to adjust. (in this case, section 2)
If you do not implement this method, the flow layout uses the value in
its section​Inset property to set the margins instead. Your
implementation of this method can return a fixed set of margin sizes
or return different margin sizes for each section.
Section insets are
margins applied only to the items in the section. They represent the
distance between the header view and the first line of items and
between the last line of items and the footer view. They also indicate
they spacing on either side of a single line of items. They do not
affect the size of the headers or footers themselves.
Option 2: (Spaghetti option, but good to know)
Create a custom subclass for section 2 items, where you can customize the inset of the actual content for the UICollectionViewCell contentView subviews.
Then in section 2, return your customized cell.

To do this, you may need to write a custom layout. Check out the Collection View Programming Guide for more information.
The default (flow) layout will always lay the cells out in this pattern:

You can achieve this type of format in UICollectionView by changing the number of sections from 1 to 2.
And then you can define your custom UICollectionViewFlowLayout accordingly for different sections.

SOLUTION: I've created a subclass of UICollectionView named "CenteringCollectionView" and with a few calculations of the sections I made it!
The .h file:
#import <UIKit/UIKit.h>
#class CenteringCollectionView;
#protocol CenteringCollectionViewDelegate <NSObject>
-(void)collectionView:(CenteringCollectionView *)collectionView didDequeueReusableCell:(UICollectionViewCell *)cell indexPath:(NSIndexPath *)indexPath;
#end
#interface CenteringCollectionView : UICollectionView
#property (nonatomic, strong) NSMutableArray *dataSourceArr;
#property (nonatomic, weak) id<CenteringCollectionViewDelegate> delegateCenteringCollection;
#end
The .m file:
#import "CenteringCollectionView.h"
#interface CenteringCollectionView () <UICollectionViewDelegate, UICollectionViewDataSource>
#property (nonatomic, assign) IBInspectable long elementsInRow;
#property (nonatomic, assign) long elementsInRowInitialValue;
#property (nonatomic) IBInspectable NSString *cellIdentifier;
#property (nonatomic) IBInspectable CGFloat cellRelativeSize; // 0..1
#property (nonatomic, assign) long numOfSections;
#property (nonatomic, assign) IBInspectable BOOL autoResize; // *** If we want auto resize - we need to set the height constraint of the collection view in size of 1 line only even if we have more than 1 line (section).
#property (nonatomic, assign)IBInspectable CGFloat heightMiddleSpacing;
#property (nonatomic, assign) long cellSize;
//#property (nonatomic, assign) CGFloat verticalTopInset;
#property (nonatomic, assign) CGFloat initialHeightConstraint;
#property (nonatomic, weak) NSLayoutConstraint *selfHeightConstraint;
#property (nonatomic, assign) CGFloat cellSpacing;
#property (nonatomic, assign) BOOL shouldReloadUIElements;
// UI IBInspectable
#property (nonatomic, weak) IBInspectable UIColor *runtimeColor;
#end
static long const maxElementsInRowDefault = 3;
#implementation CenteringCollectionView
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
self.elementsInRow = maxElementsInRowDefault; // will get the default value if not stored value in storyboard
self.elementsInRowInitialValue = self.elementsInRow;
self.cellRelativeSize = 0.5;
self.initialHeightConstraint = -1;
}
return self;
}
-(void)setDataSourceCount:(long)dataSourceCount
{
if (dataSourceCount == _dataSourceCount)
{
return;
}
_dataSourceCount = dataSourceCount;
self.shouldReloadUIElements = YES;
self.elementsInRow = MIN(self.elementsInRowInitialValue, self.dataSourceCount);
self.numOfSections = ceil((CGFloat)self.dataSourceCount / (CGFloat)self.elementsInRow);
CGFloat selfHeight = [self handleAutoResizeAndReturnTheNewHeightIfNeeded];
CGFloat selfWidth = CGRectGetWidth(self.frame);
CGFloat cellWidth = (selfWidth / self.elementsInRow) * self.cellRelativeSize;
CGFloat cellHeight = (selfHeight / self.numOfSections) * self.cellRelativeSize;
self.cellSize = MIN(cellWidth, cellHeight);
dispatch_async(dispatch_get_main_queue(), ^{
[self setCollectionView];
[self reloadData];
});
}
-(void)awakeFromNib
{
[super awakeFromNib];
self.elementsInRowInitialValue = self.elementsInRow;
[self handleUIelementsIBInspectable];
}
-(void)handleUIelementsIBInspectable
{
if (self.runtimeColor)
{
[self setBackgroundColor:self.runtimeColor];
}
}
-(CGFloat)handleAutoResizeAndReturnTheNewHeightIfNeeded
{
if (self.autoResize)
{
for (NSLayoutConstraint *constraint in [self constraints])
{
if (constraint.firstAttribute == NSLayoutAttributeHeight)
{
if (self.initialHeightConstraint == -1) // not set yet
{
self.initialHeightConstraint = constraint.constant;
}
if (!self.selfHeightConstraint)
{
self.selfHeightConstraint = constraint;
}
CGFloat newHeight = self.initialHeightConstraint * self.numOfSections;
constraint.constant = newHeight;
if (self.bounds.size.height != newHeight)
{
CGRect frame = self.bounds;
frame.size.height = newHeight;
[self setBounds:frame];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.superview layoutIfNeeded];
[self layoutIfNeeded];
});
return newHeight;
}
}
}
return CGRectGetHeight(self.frame);
}
-(long)numOfSpacesInRow
{
return self.elementsInRow + 1;
}
-(long)numOfSpacesBetweenLines
{
return self.numOfSections + 1;
}
-(void)setCellRelativeSize:(CGFloat)cellRelativeSize
{
_cellRelativeSize = MAX(0, MIN(cellRelativeSize, 1));
}
-(void)setCollectionView
{
[self reloadData];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
CGFloat horizontalCellSpacing = ((CGRectGetWidth(self.frame) - (self.cellSize * self.elementsInRow)) / self.numOfSpacesInRow);
CGFloat verticalCellSpacing = (CGRectGetHeight(self.frame) - (self.numOfSections * self.cellSize)) / self.numOfSpacesBetweenLines;
self.cellSpacing = MAX(MIN(horizontalCellSpacing, verticalCellSpacing), 0);
[layout setMinimumInteritemSpacing:self.cellSpacing];
[layout setMinimumLineSpacing:self.cellSpacing];
[layout setScrollDirection:UICollectionViewScrollDirectionVertical];
[self setCollectionViewLayout:layout];
self.showsVerticalScrollIndicator = NO;
self.showsHorizontalScrollIndicator = NO;
self.scrollEnabled = NO;
if (!self.delegate)
{
self.delegate = self;
self.dataSource = self;
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.cellSize, self.cellSize);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
BOOL isLastSection = (section == self.numOfSections - 1);
if (isLastSection == NO)
{
return self.elementsInRow;
}
else
{
long numOfLeftItemsInLastRow = self.dataSourceCount % self.elementsInRow;
if (numOfLeftItemsInLastRow == 0)
{
return self.elementsInRow;
}
else
{
return numOfLeftItemsInLastRow;
}
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:self.cellIdentifier forIndexPath:indexPath];
if ([self.delegateCenteringCollection respondsToSelector:#selector(collectionView:didDequeueReusableCell:indexPath:)])
{
[self.delegateCenteringCollection collectionView:self didDequeueReusableCell:cell indexPath:[self indexPathWithoutSectionsFrom:indexPath]];
}
return cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.delegateCenteringCollection respondsToSelector:#selector(collectionView:didSelectItemAtIndexPath:cell:)])
{
UICollectionViewCell *selectedCell = [collectionView cellForItemAtIndexPath:indexPath];
[self.delegateCenteringCollection collectionView:self didSelectItemAtIndexPath:[self indexPathWithoutSectionsFrom:indexPath] cell:selectedCell];
}
}
-(NSIndexPath *)indexPathWithoutSectionsFrom:(NSIndexPath *)indexPath
{
long sectionNum = indexPath.section;
long rowNum = sectionNum * self.elementsInRow + indexPath.row;
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:rowNum inSection:0];
return newIndexPath;
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.numOfSections;
}
-(void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
dispatch_async(dispatch_get_main_queue(), ^{
if (self.shouldReloadUIElements == NO)
{
return;
}
if (self.autoResize && self.selfHeightConstraint)
{
BOOL isTheFirstCellInTheLastSection = (indexPath.section == self.numOfSections - 1) && indexPath.row == 0;
if (isTheFirstCellInTheLastSection)
{
CGFloat newHeight = CGRectGetMaxY(cell.frame) + self.cellSpacing;
self.selfHeightConstraint.constant = newHeight;
if (self.bounds.size.height != newHeight)
{
CGRect frame = self.bounds;
frame.size.height = newHeight;
[self setBounds:frame];
}
[self.superview layoutIfNeeded];
[self layoutIfNeeded];
}
}
});
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
if (self.shouldReloadUIElements == NO)
{
return collectionView.contentInset;
}
NSInteger cellsCount = [collectionView numberOfItemsInSection:section];
CGFloat horizontalInset = (collectionView.bounds.size.width - (cellsCount * self.cellSize) - ((cellsCount - 1) * self.cellSpacing)) * 0.5;
horizontalInset = MAX(horizontalInset, 0.0);
BOOL isLastSection = (section == self.numOfSections - 1);
CGFloat verticalTopInset = self.cellSpacing;
CGFloat verticalBottomInset = verticalTopInset;
if (section == 0 && isLastSection == NO)
{
if (self.heightMiddleSpacing)
{
verticalBottomInset += self.heightMiddleSpacing;
}
verticalBottomInset /= 2;
}
if (section > 0)
{
if (self.heightMiddleSpacing)
{
verticalTopInset += self.heightMiddleSpacing;
}
verticalTopInset /= 2;
if (isLastSection == NO)
{
if (self.heightMiddleSpacing)
{
verticalBottomInset += self.heightMiddleSpacing;
}
verticalBottomInset /= 2;
}
}
return UIEdgeInsetsMake(verticalTopInset, horizontalInset, verticalBottomInset, horizontalInset);
}
#end
And to make it work, all we need to do in the parent view is:
self.collectionView.delegateCenteringCollection = self;
self.collectionView.dataSourceCount = 5; // Or whatever number we want!
In the storyboard: we need to create collectionView of this class and set the "elements in row" value, also set the "Cell Identifier" and the "Cell relative size" between 0 to 1 (the "Cell relative size" value: will calculate the cell size & paddings according to the collectionView width & height).
And at last - set "autoResize" to "true" if you want that the collection view will resize its own height constraint(if exist) automatically according to the number of rows. If we set "autoResize" to true, the height constraint that we set to the collectionView will determine the height of a single row. If our collectionView should grow for example to 3 rows, it will multiple our collectionview height constraint by 3.
And it works like a charm!

Related

IOS Tabbar scrolling animation: Text changing color on touch with indicator view

I want to make an animation that when you scroll the tabbar, the indicator view follow and when it touch on the text of the tab, that text change color only the part it being touched.
Example like in the picture below.
How can I achieve this ? I have been racking my brain the whole day and no solution come to mind.
https://i.stack.imgur.com/ZrkZy.png
[PageCollectionViewCell.h]//You can change this cell with your favorite style.
#interface PageCollectionViewCell : UICollectionViewCell
/**
title Label
*/
#property (nonatomic, strong) UILabel *pageLabel;
/**
itemWidth
*/
#property (nonatomic, assign) CGFloat itemWidth;
#end
[PageCollectionViewCell.m]
#import "PageCollectionViewCell.h"
#interface PageCollectionViewCell ()
/**
title lab Margin
*/
#property (nonatomic, assign) CGFloat inset;
/**
border color
*/
#property (nonatomic, strong) UIColor *hexColor;
#end
#implementation PageCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.inset = 5;
self.hexColor = [UIColor orangeColor];
[self configSubView];
}
return self;
}
- (void)configSubView {
UILabel *pageLabel = [[UILabel alloc] init];
[pageLabel setTextColor:self.hexColor];
pageLabel.layer.borderColor = self.hexColor.CGColor;
pageLabel.layer.borderWidth = 2;
[pageLabel setTextAlignment:NSTextAlignmentCenter];
pageLabel.clipsToBounds = YES;
[self addSubview:pageLabel];
self.pageLabel = pageLabel;
[pageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self).insets(UIEdgeInsetsMake(self.inset, self.inset, self.inset, self.inset));
}];
self.pageLabel = pageLabel;
}
#pragma mark - set selected status
- (void)setSelected:(BOOL)isSelected {
[self.pageLabel setTextColor:isSelected ? UIColor.whiteColor : self.hexColor];
self.pageLabel.backgroundColor = isSelected ? self.hexColor : UIColor.clearColor;
}
- (void)setItemWidth:(CGFloat)itemWidth {
self.pageLabel.layer.cornerRadius = (itemWidth - 2 * self.inset) / 2;
}
#end
[ViewViewController.m]
#import "ViewViewController.h"
#import "PageCollectionViewCell.h"
static NSString *kCellID = #"cellID";
#interface ViewViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>
#property (nonatomic, strong) NSArray *arr;//page color
#property (nonatomic, strong) UICollectionView *pageCollectionView;
#property (nonatomic, assign) CGFloat itemWidth;//itemWidth
#property (nonatomic, strong) UIScrollView *pageScrollView;
#end
#implementation ViewViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.itemWidth = 40;
self.arr = [NSArray arrayWithObjects:[UIColor blueColor],[UIColor redColor],[UIColor yellowColor],[UIColor orangeColor],[UIColor greenColor], nil];
[self configNavigationBar];
[self configPageView];
}
- (void)configNavigationBar {
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flowLayout.itemSize = CGSizeMake(self.itemWidth, self.itemWidth);
flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
flowLayout.minimumLineSpacing = 0;
UICollectionView *pageCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.itemWidth * self.arr.count, NavigationBar_Height) collectionViewLayout:flowLayout];
pageCollectionView.dataSource = self;
pageCollectionView.delegate = self;
pageCollectionView.backgroundColor = UIColor.clearColor;
[pageCollectionView registerClass:[PageCollectionViewCell class] forCellWithReuseIdentifier:kCellID];
self.navigationItem.titleView = pageCollectionView;
NSIndexPath *firstIndexpath = [NSIndexPath indexPathForItem:0 inSection:0];
[pageCollectionView selectItemAtIndexPath:firstIndexpath animated:YES scrollPosition:UICollectionViewScrollPositionBottom];
self.pageCollectionView = pageCollectionView;
}
- (void)configPageView {
//define in pch file
CGFloat navigationBar_height = self.navigationController.navigationBar.frame.size.height;
CGFloat statusBar_height = [UIApplication sharedApplication].statusBarFrame.size.height;
CGFloat homeIndicator_Height = (statusBar_height > 20.0 ? 34.0 : 0.0);
CGFloat screen_width = self.view.frame.size.width;
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, navigationBar_height + statusBar_height, screen_width, self.view.frame.size.height - navigationBar_height - statusBar_height - homeIndicator_Height)];
pageScrollView.pagingEnabled = YES;
pageScrollView.delegate = self;
pageScrollView.showsVerticalScrollIndicator = NO;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.contentSize = CGSizeMake(screen_width * self.arr.count, 0);
[self.view addSubview:pageScrollView];
self.pageScrollView = pageScrollView;
for (NSInteger index = 0; index < self.arr.count; index++) {
UIView *pageView = [[UIView alloc] initWithFrame:CGRectMake(index * self.pageScrollView.frame.size.width, 0, self.pageScrollView.frame.size.width, self.pageScrollView.frame.size.height)];
pageView.backgroundColor = self.arr[index];
[self.pageScrollView addSubview:pageView];
}
}
#pragma mark - UICollectionViewDelegate, UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return self.arr.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PageCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
cell.pageLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.item + 1];
cell.itemWidth = self.itemWidth;
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat screen_width = self.view.frame.size.width;
[self.pageScrollView setContentOffset:CGPointMake(indexPath.item * screen_width, 0) animated:YES];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (!scrollView.isDragging && !scrollView.isDecelerating) {
return;
}
CGFloat screen_width = self.view.frame.size.width;
NSIndexPath *currentIndexpath = [NSIndexPath indexPathForItem:((scrollView.contentOffset.x - screen_width / 2) / screen_width) + 1 inSection:0];
[self.pageCollectionView selectItemAtIndexPath:currentIndexpath animated:YES scrollPosition:UICollectionViewScrollPositionBottom];
}
#end

Collection View Cell Size Is Not As Expected

I'm trying to make a custom keyboard using storyboard. I need to use two collection views. I want the height and width of collection view cell as the height of collection view itself. Constraints are set properly. But cell size is not looking as expected. It is same as what height collection view has on the storyboard.
Here is the code.
#import "MainViewController.h"
#import "UpperCollectionViewCell.h"
#import "LowerCollectionViewCell.h"
#interface MainViewController () <UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property (weak, nonatomic) IBOutlet UICollectionView *upperCollectionView;
#property (weak, nonatomic) IBOutlet UICollectionView *lowerCollectionView;
#property (strong, nonatomic) NSArray *upperData;
#property (strong, nonatomic) NSArray *lowerData;
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"View Presented");
self.lowerCollectionView.delegate = self;
self.lowerCollectionView.dataSource = self;
self.upperCollectionView.delegate = self;
self.upperCollectionView.dataSource = self;
self.upperData = #[[[DataModel alloc] initWithTitle:#"Bollywood" subtitle:nil color:[UIColor orangeColor]],
[[DataModel alloc] initWithTitle:#"Hollywood" subtitle:nil color:[UIColor greenColor]],
[[DataModel alloc] initWithTitle:#"Tollywood" subtitle:nil color:[UIColor magentaColor]]];
self.lowerData = #[[[DataModel alloc] initWithTitle:#"News" subtitle:#"Very first comment" color:[UIColor blueColor]],
[[DataModel alloc] initWithTitle:#"Tasks" subtitle:#"Second comment" color:[UIColor redColor]],
[[DataModel alloc] initWithTitle:#"Events" subtitle:#"Third comment" color:[UIColor greenColor]]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
if(collectionView == self.lowerCollectionView) {
return self.lowerData.count;
}
else if(collectionView == self.upperCollectionView) {
return self.upperData.count;
}
else {
return 0;
}
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
if(collectionView == self.lowerCollectionView) {
LowerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"lower_cv_cell" forIndexPath:indexPath];
[cell setDataModel:self.lowerData[indexPath.row]];
[cell layoutIfNeeded];
return cell;
}
else if(collectionView == self.upperCollectionView) {
UpperCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"upper_cv_cell" forIndexPath:indexPath];
[cell setDataModel:self.upperData[indexPath.row]];
[cell layoutIfNeeded];
return cell;
}
else {
return nil;
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if(collectionView == self.lowerCollectionView) {
CGSize size = CGSizeMake(collectionView.bounds.size.height, collectionView.bounds.size.height-10);
NSLog(#"lower height : %#",NSStringFromCGSize(size));
return size;
}
else if(collectionView == self.upperCollectionView) {
CGSize size = CGSizeMake(collectionView.bounds.size.height, collectionView.bounds.size.height-10);
NSLog(#"upper height : %#",NSStringFromCGSize(size));
return size;
}
else {
return CGSizeZero;
}
}
#end
Unable to figure out why cell size is not as expected.

CALayer inside UICollectionViewCell pinch

I added a GIF to describe a problem. I have a UICollectionView with a lot of cells and each cell has a CALayer inside. I have a pinch gesture in my UICollectionView. When it zooming in it looks like each cell zooming apart. See spaces between cells on gif. Is it possible to zoom in each cells together? Thanks in advance
Code:
Cell subclass
#property (nonatomic, strong) CALayer *circularLayer;
- (void)layoutSubviews
{
[self updateRoundedCorners];
}
- (void)updateRoundedCorners
{
CGRect bounds = self.bounds;
self.circularLayer.bounds = bounds;
self.circularLayer.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
}
#pragma mark - Property Set
- (void)setCellObject:(VenueLayoutCellObject *)cellObject
{
self->_cellObject = cellObject;
self.objectBackgroundColor = cellObject.objectColor;
self.type = cellObject.type;
}
Controller
- (void)didReceivePinchGesture:(UIPinchGestureRecognizer *)gesture
{
static CGFloat scaleStart;
if (gesture.state == UIGestureRecognizerStateBegan) {
scaleStart = self.venueLayoutZoom;
}
else if (gesture.state == UIGestureRecognizerStateChanged) {
self.venueLayoutZoom = scaleStart * gesture.scale;
[self.activeCollectionView.collectionViewLayout invalidateLayout];
}
}
Updated:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
VenueLayoutCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kVenueLayoutCellReuseIdentifier forIndexPath:indexPath];
self.activeCollectionViewCellsDictionary[indexPath] = cell;
if (self.activeCollectionViewObjects.count > indexPath.section) {
NSArray *rows = self.activeCollectionViewObjects[indexPath.section];
if (rows.count > indexPath.row) {
if ([rows[indexPath.row] isKindOfClass:[VenueLayoutCellObject class]]) {
VenueLayoutCellObject *object = rows[indexPath.row];
cell.cellObject = object;
}
}
}
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
CGFloat widthAndHeight = [self widthAndHeightForActiveCollectionViewItem];
return CGSizeMake(widthAndHeight *self.venueLayoutZoom, widthAndHeight * self.venueLayoutZoom);
}
- (CGFloat)widthAndHeightForActiveCollectionViewItem
{
NSArray *array = self.activeCollectionViewObjects;
__block NSInteger maxCount = 0;
[array enumerateObjectsUsingBlock:^(NSArray *subArray, NSUInteger idx, BOOL * _Nonnull stop) {
if (subArray.count > maxCount) {
maxCount = subArray.count;
}
}];
CGFloat widthAndHeight = CGRectGetWidth(self.activeCollectionView.bounds) / maxCount;
return widthAndHeight;
}
The changes you are making to the layer are implicitly animated, meaning that they are performed with an animation, even though you haven't specifically told them to.
Since you're responding to user gestures, you don't want the changes to be animated as this is making them lag behind the gesture.
You can turn off implicit animations during layoutSubviews like this:
- (void)layoutSubviews
{
[super layoutSubviews];
[CATransaction begin];
[CATransaction setDisableActions: YES];
[self updateRoundedCorners];
[CATransaction commit];
}
Cell subclass
#property (nonatomic, strong) CALayer *circularLayer;
- (void)layoutSubviews
{
[super layoutSubviews];
[self updateRoundedCorners];
}
The only problem I see with this code importantly is missing [super layoutSubviews];
If it doesn't work do provide more code.

Horizontaly centered UICollectionView cells with custom paging

I'm currently building an app that has to present a twitter feed in the form of an horizontal collection view.
3 tweets (cells) should always be visible on screen and centered horizontaly aswell as half a tweet (last element of the previous 3 and first element of the next 3) on both side.
Here is a picture so it's easier to understand
When the user scrolls it should scroll 3 by 3 (or less if there are actualy less cell left to scroll). Sort of a custom paging.
I tried using a Custom layout and it works and make the cells be centered, showing half tweets on both side just like I want. But I can't make it work with the scrolling I want (3by3). And it won't let me show the first or last cell entirely... Anyway, when I had the following code, it just cancel the custom layout behaviour, but scrolls 3 by 3...
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
float pageWidth = ((self.view.frame.size.width / 4)*3);
float currentOffset = scrollView.contentOffset.x;
float targetOffset = targetContentOffset->x;
float newTargetOffset = 0;
if (targetOffset > currentOffset)
newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth;
else
newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth;
if (newTargetOffset < 0)
newTargetOffset = 0;
else if (newTargetOffset > scrollView.contentSize.width)
newTargetOffset = scrollView.contentSize.width;
targetContentOffset->x = currentOffset;
[scrollView setContentOffset:CGPointMake(newTargetOffset, 0) animated:YES];
}
So guys, has anyone played with this before and could help me get things done ? Thanks a bunch.
ViewController.h
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#import "DetailimageViewController.h"
#interface RootViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
{
IBOutlet UICollectionView *collectionViewHorizontalVertical;
}
ViewController.m
#import "RootViewController.h"
#interface RootViewController ()
{
NSMutableArray *arrayImages;
DetailimageViewController *detailImageVC ;
}
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
arrayImages = [[NSMutableArray alloc]initWithObjects:#"iMove.jpg",#"iPad.jpg",#"iPhone.jpg",#"iPod.jpg",#"iRing.jpg",#"iTV.jpg",#"iwatch.jpeg",nil];
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
UINib *cellNib = [UINib nibWithNibName:#"CustomCell" bundle:nil];
[collectionViewHorizontalVertical registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
}
//UICollectionView DataSource and Delegate Methods
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return arrayImages.count;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cvCell";
CustomCell *cell = (CustomCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.imgViewCollection.image = [UIImage imageNamed:[arrayImages objectAtIndex:indexPath.row]];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"The indexPath is - %ld",(long)indexPath.item);
int ind = (int)indexPath.item;
detailImageVC = [[DetailimageViewController alloc]initWithNibName:#"DetailimageViewController" bundle:nil];
detailImageVC.arrayImagesCount = arrayImages;
detailImageVC.intSelectedIndex = ind;
[[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:#"%d",detailImageVC.intSelectedIndex] forKey:#"SelectedCollectionViewID"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.navigationController pushViewController:detailImageVC animated:YES];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(200, 200);
}
#end
In above coding I have 7 images.So you need to have your images above 7 or less.It is your wish.
Then DetailimageViewController.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface DetailimageViewController : UIViewController<UIScrollViewDelegate>
{
}
#property (strong, nonatomic) NSMutableArray *arrayImagesCount;
#property (strong, nonatomic) IBOutlet UIScrollView *scroll;
#property (strong, nonatomic) IBOutlet UIPageControl *pageControl;
#property (strong, nonatomic) IBOutlet UIImageView *imageviewScrollView
#property (assign, nonatomic) NSInteger seletedIndex;
#property (strong, nonatomic) UIImage *imageSelection;
#property (nonatomic, assign) int intSelectedIndex;
#property (nonatomic, strong) NSArray *pageImages;
#property (nonatomic, assign) CGFloat lastContentOffset;
- (IBAction)actionBack:(id)sender;
#end
DetailimageViewController.m
#import "DetailimageViewController.h"
#interface DetailimageViewController ()
{
UIImageView *subimg;
}
#end
#implementation DetailimageViewController
typedef enum ScrollDirection
{
ScrollDirectionNone,
ScrollDirectionRight,
ScrollDirectionLeft,
ScrollDirectionUp,
ScrollDirectionDown,
ScrollDirectionCrazy,
} ScrollDirection;
#synthesize arrayImagesCount;
#synthesize scroll;
#synthesize seletedIndex;
#synthesize imageSelection;
#synthesize intSelectedIndex;
#synthesize pageImages = _pageImages;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
scroll.layer.cornerRadius=8.0f;
scroll.layer.masksToBounds=YES;
scroll.layer.borderColor=[[UIColor redColor]CGColor];
scroll.layer.borderWidth= 1.0f;
NSInteger pageCount = arrayImagesCount.count;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int intCollectionViewIndex = [[defaults valueForKey:#"SelectedCollectionViewID"]intValue];
if(intSelectedIndex == intCollectionViewIndex)
{
for (int i=intSelectedIndex; i<[arrayImagesCount count]; i++)
{
CGRect frame;
if(i == intCollectionViewIndex)
{
frame.origin.x = self.scroll.frame.size.width *intCollectionViewIndex;
frame.origin.y=0;
frame.size=self.scroll.frame.size;
subimg=[[UIImageView alloc]initWithFrame:CGRectMake(self.scroll.frame.size.width *intCollectionViewIndex,0,self.scroll.frame.size.width,self.scroll.frame.size.height)];
subimg.image=[UIImage imageNamed:[NSString stringWithFormat:#"%#",[arrayImagesCount objectAtIndex:i]]];
[self.scroll addSubview:subimg];
[self.scroll setContentOffset:CGPointMake(self.scroll.frame.size.width*i,-20) animated:YES];
self.scroll.contentSize = CGSizeMake(self.scroll.frame.size.width*arrayImagesCount.count, self.scroll.frame.size.height);
}
else{
}
}
}
}
ScrollView Delegate Method
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(#" Offset = %# ",NSStringFromCGPoint(scrollView.contentOffset));
ScrollDirection scrollDirection;
if (self.lastContentOffset > scrollView.contentOffset.x)
{
scrollDirection = ScrollDirectionRight;
NSLog(#"The scrollview is scrolling right side");
for(int j=intSelectedIndex;j<[arrayImagesCount count];j--)
{
CGRect frameRight;
frameRight.origin.x = self.scroll.frame.size.width *j;
frameRight.origin.y=0;
frameRight.size=self.scroll.frame.size;
subimg=[[UIImageView alloc]initWithFrame:CGRectMake(self.scroll.frame.size.width *j,0,self.scroll.frame.size.width,self.scroll.frame.size.height)];
subimg.image=[UIImage imageNamed:[NSString stringWithFormat:#"%#",[arrayImagesCount objectAtIndex:j]]];
[self.scroll addSubview:subimg];
self.scroll.contentSize = CGSizeMake(self.scroll.frame.size.width*arrayImagesCount.count, self.scroll.frame.size.height);
}
}
else if (self.lastContentOffset < scrollView.contentOffset.x)
{
scrollDirection = ScrollDirectionLeft;
NSLog(#"The scrollview is scrolling left side");
for(int k=intSelectedIndex;k<[arrayImagesCount count];k++)
{
CGRect frameLeft;
frameLeft.origin.x = self.scroll.frame.size.width *k;
frameLeft.origin.y=0;
frameLeft.size=self.scroll.frame.size;
subimg=[[UIImageView alloc]initWithFrame:CGRectMake(self.scroll.frame.size.width *k,0,self.scroll.frame.size.width,self.scroll.frame.size.height)];
subimg.image=[UIImage imageNamed:[NSString stringWithFormat:#"%#",[arrayImagesCount objectAtIndex:k]]];
[self.scroll addSubview:subimg];
self.scroll.contentSize = CGSizeMake(self.scroll.frame.size.width*arrayImagesCount.count, self.scroll.frame.size.height);
}
}
self.lastContentOffset = scrollView.contentOffset.x;
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
CGPoint translation = [scrollView.panGestureRecognizer translationInView:scrollView.superview];
NSLog(#"The translation.x is - %f",translation.x);
NSLog(#"The scrollview content off set is - %f",scrollView.contentOffset.x);
if ([scrollView.panGestureRecognizer translationInView:scrollView.superview].x > 0) {
// handle dragging to the right
NSLog(#"It is dragging to right side");
} else {
// handle dragging to the left
NSLog(#"It is dragging to left side");
}
}
- (IBAction)actionBack:(id)sender
{
[self.navigationController popViewControllerAnimated:YES];
}
#end

UICollectionView Layout customization

I have a lot of section and items. When I touch button in cell it create cell with 4 items in 1 cell (like expanded table) touch again cell disappear.
I found WaterfallCollectionView and there I can change height of items.
What is the best way to achieve this???
Structure like:
----- -----
| +| | +| and other rows
| | | |
----- -----
When I touch my button (+) it should be like:
----- ----- -----
| -| |__|__| | +|
| | | | | | |
----- ----- -----
A new cell create with 4 UIImageView's inside 1 cell ( if 4 elements in 1 cell, if more create more cell). If 1 element create this cell but image will be in the top left corner.
Where in cells should be my info (like expanded table)
Is it better to create different type of cells?
I tried something out where a UICollectionViewCell is made to expand by changing its own size. The new 'cells' that pop out when you tap on a cell are not really new cells, but subviews of the original cell. Essentially it works something like this:
Use UICollectionView with a UICollectionViewFlowLayout.
The UICollectionView's delegate conforms to UICollectionViewDelegateFlowLayout and implements -collectionView:layout:sizeForItemAtIndexPath: to recognize unique cell sizes.
The UICollectionView's delegate implements -collectionView:didSelectCellAtIndexPath: where it adjusts the cell's size to reveal or hide the subviews that look like new cells.
A custom object representing the cell's contents and a custom UICollectionViewCell subclass are used to make it easier to perform and keep track of expansion.
I created an example project here which has a cells that expand to show a number's divisors. It looks something like this:
The project is pretty rough and uncommented, and the transition happens without animation, but if you find this approach interesting and cannot follow the code I can clean it up a bit.
And here's the code dump...
CollectionViewController.h
#import <UIKit/UIKit.h>
#interface CollectionViewController : UIViewController
#end
CollectionViewController.m
#import "CollectionViewController.h"
#import "CellDataItem.h"
#import "CollectionViewCell.h"
#interface CollectionViewController () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property (strong, nonatomic) UICollectionView *collectionView;
#property (strong, nonatomic) NSMutableArray *cellData;
#end
NSString *const kCollectionViewCellIdentifier = #"Cell";
#implementation CollectionViewController
- (NSMutableArray *)cellData
{
if (!_cellData) {
NSInteger countValues = 20;
_cellData = [[NSMutableArray alloc] initWithCapacity:countValues];
for (NSInteger i = 0; i < countValues; i++) {
CellDataItem *item = [[CellDataItem alloc] init];
item.number = #(arc4random() % 100);
[_cellData addObject:item];
}
}
return _cellData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor grayColor];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = [CollectionViewCell sizeWithDataItem:nil];
layout.minimumInteritemSpacing = [CollectionViewCell margin];
layout.minimumLineSpacing = layout.minimumInteritemSpacing;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor darkGrayColor];
_collectionView.dataSource = self;
_collectionView.delegate = self;
[self.view addSubview:_collectionView];
[_collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:kCollectionViewCellIdentifier];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
self.collectionView.frame = CGRectMake(0.0f, 0.0f, self.view.bounds.size.width, layout.itemSize.height);
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.cellData.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCollectionViewCellIdentifier
forIndexPath:indexPath];
cell.dataItem = [self.cellData objectAtIndex:indexPath.row];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return [CollectionViewCell sizeWithDataItem:[self.cellData objectAtIndex:indexPath.row]];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = (CollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
[cell toggleExpansion];
[collectionView reloadData];
}
#end
#import <Foundation/Foundation.h>
#interface CellDataItem : NSObject
#property (strong, nonatomic) NSNumber *number;
#property (nonatomic, readonly) NSArray *divisors;
#property (nonatomic, getter = isExpanded) BOOL expanded;
#end
CellDataItem.m
#import "CellDataItem.h"
#interface CellDataItem ()
#property (strong, nonatomic) NSArray *divisors;
#end
#implementation CellDataItem
+ (NSArray *)divisorsForNumber:(NSNumber *)number
{
NSMutableArray *divisors = [NSMutableArray arrayWithObjects:#(1), number, nil];
float root = pow(number.doubleValue, 0.5);
if (root == roundf(root)) {
[divisors addObject:[NSNumber numberWithInteger:(NSInteger)root]];
}
NSInteger maxDivisor = (NSInteger)root;
for (NSInteger divisor = 2; divisor < maxDivisor; divisor++) {
float quotient = number.floatValue / (float)divisor;
if (quotient == roundf(quotient)) {
[divisors addObject:[NSNumber numberWithInteger:divisor]];
[divisors addObject:[NSNumber numberWithInteger:(NSInteger)quotient]];
}
}
return [divisors sortedArrayUsingSelector:#selector(compare:)];
}
- (void)setNumber:(NSNumber *)number
{
if (_number == number) {
return;
}
_number = number;
self.divisors = [self.class divisorsForNumber:_number];
}
#end
CollectionViewCell.h
#import <UIKit/UIKit.h>
#class CellDataItem;
#interface CollectionViewCell : UICollectionViewCell
+ (CGFloat)margin;
+ (CGSize)sizeWithDataItem:(CellDataItem *)dataItem;
#property (strong, nonatomic) CellDataItem *dataItem;
- (void)toggleExpansion;
#end
#interface ChildView : UIView
- (UILabel *)labelAtIndex:(NSInteger)index;
- (void)clearLabels;
#end
CollectionViewCell.m
#import "CollectionViewCell.h"
#import <QuartzCore/QuartzCore.h>
#import "CellDataItem.h"
#interface CollectionViewCell ()
#property (strong, nonatomic) NSMutableArray *childViews;
#property (strong, nonatomic) UILabel *numberLabel;
#end
NSInteger const kCollectionViewCellSplitCount = 4;
CGFloat const kCollectionViewCellMargin = 20.0f;
CGSize const kCollectionViewCellDefaultSize = {200.0f, 200.0f};
#implementation CollectionViewCell
+ (CGFloat)margin
{
return kCollectionViewCellMargin;
}
+ (CGSize)sizeWithDataItem:(CellDataItem *)dataItem
{
if (dataItem && dataItem.isExpanded) {
CGSize size = kCollectionViewCellDefaultSize;
NSInteger childViewsRequired = [self childViewsRequiredForDataItem:dataItem];
size.width += childViewsRequired * ([self margin] + size.width);
return size;
} else {
return kCollectionViewCellDefaultSize;
}
}
+ (NSInteger)childViewsRequiredForDataItem:(CellDataItem *)dataItem
{
return (NSInteger)ceilf((float)dataItem.divisors.count / (float)kCollectionViewCellSplitCount);
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_numberLabel = [[UILabel alloc] init];
_numberLabel.textAlignment = NSTextAlignmentCenter;
_numberLabel.layer.borderColor = [UIColor blackColor].CGColor;
_numberLabel.layer.borderWidth = 1.0f;
_numberLabel.backgroundColor = [UIColor whiteColor];
[self.contentView addSubview:_numberLabel];
}
return self;
}
- (void)setDataItem:(CellDataItem *)dataItem
{
if (_dataItem == dataItem) {
return;
}
_dataItem = dataItem;
self.numberLabel.text = [NSString stringWithFormat:#"%i", dataItem.number.integerValue];
if (!dataItem.expanded) {
[self collapse];
} else if (dataItem.expanded) {
[self expand];
}
}
- (void)collapse
{
for (ChildView *view in self.childViews) {
view.hidden = YES;
}
}
- (void)expand
{
NSInteger childViewsRequired = [self.class childViewsRequiredForDataItem:self.dataItem];
while (self.childViews.count < childViewsRequired) {
ChildView *childView = [[ChildView alloc] init];
[self.childViews addObject:childView];
[self.contentView addSubview:childView];
}
NSInteger index = 0;
for (ChildView *view in self.childViews) {
view.hidden = !(index < childViewsRequired);
if (!view.hidden) {
[view clearLabels];
}
index++;
}
for (NSInteger i = 0; i < self.dataItem.divisors.count; i++) {
NSInteger labelsPerChild = 4;
NSInteger childIndex = i / labelsPerChild;
NSInteger labelIndex = i % labelsPerChild;
[[[self.childViews objectAtIndex:childIndex] labelAtIndex:labelIndex] setText:[NSString stringWithFormat:#"%i", [[self.dataItem.divisors objectAtIndex:i] integerValue]]];
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat const unitWidth = kCollectionViewCellDefaultSize.width;
CGFloat const unitHeight = kCollectionViewCellDefaultSize.height;
CGFloat const margin = [self.class margin];
self.numberLabel.frame = CGRectMake(0.0f, 0.0f, unitWidth, unitHeight);
for (NSInteger i = 0; i < self.childViews.count; i++) {
ChildView *view = [self.childViews objectAtIndex:i];
view.frame = CGRectMake((i + 1) * (margin + unitWidth), 0.0f, unitWidth, unitHeight);
}
}
- (NSMutableArray *)childViews
{
if (!_childViews) {
_childViews = [[NSMutableArray alloc] init];
}
return _childViews;
}
- (void)toggleExpansion
{
self.dataItem.expanded = !self.dataItem.isExpanded;
if (self.dataItem.isExpanded) {
[self expand];
} else {
[self collapse];
}
}
#end
#interface ChildView ()
#property (strong, nonatomic) NSMutableArray *labels;
#end
#implementation ChildView
- (id)init
{
if ((self = [super init])) {
self.backgroundColor = [UIColor lightGrayColor];
}
return self;
}
- (UILabel *)labelAtIndex:(NSInteger)index
{
if (!self.labels) {
self.labels = [NSMutableArray array];
}
while (self.labels.count <= index) {
UILabel *label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentCenter;
label.layer.borderColor = [UIColor blackColor].CGColor;
label.layer.borderWidth = 1.0f;
[self.labels addObject:label];
[self addSubview:label];
}
return [self.labels objectAtIndex:index];
}
- (void)clearLabels
{
for (UILabel *label in self.labels) {
label.text = nil;
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat labelWidth = self.bounds.size.width * 0.5f;
CGFloat labelHeight = self.bounds.size.height * 0.5f;
for (NSInteger i = 0; i < self.labels.count; i++) {
UILabel *label = [self.labels objectAtIndex:i];
NSInteger x = i % 2;
NSInteger y = i / 2;
label.frame = CGRectMake(x * labelWidth, y * labelHeight, labelWidth, labelHeight);
}
}
#end
If you want expandable cells you have to insert the new cells inside the collection view by calling insertItemsAtIndexPaths: on your collection view.
It is not trivial as you have to shift all your index paths, update the number of items in the section to reflect the newly added cells, etc. If you are looking for something simple then the Waterfall example is good. If you want a more complex / configurable solution then you have to rock your own custom layout. That's what I did.

Resources