Wrong UICollectionViewCell size - ios

I want to change size of my UICollectionViewCell
In Interface Builder I set custom size
In my code I want change size of cell
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(274, 274);
}
In future I need have different size of cell
In my cell I have next method
- (void)awakeFromNib
{
backImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.width, self.height / 1.32)];
[self addSubview:backImageView];
lineImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, backImageView.height, self.width, self.height / 9.67)];
[self addSubview:lineImageView];
nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(28, lineImageView.originY + 5, self.width - 28, 15)];
nameLabel.font = [UIFont fontWithName:FontStyleBold size:14];
[self addSubview:nameLabel];
descriptLabel = [[UILabel alloc] initWithFrame:CGRectMake(nameLabel.originX, lineImageView.originY + lineImageView.height + 3, nameLabel.width - nameLabel.originX, 25)];
descriptLabel.numberOfLines = 2;
descriptLabel.font = [UIFont fontWithName:FontStyle size:8];
[self addSubview:descriptLabel];
self.backgroundColor = [UIColor whiteColor];
self.layer.masksToBounds = NO;
self.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(-1, 2.0, self.width + 2, self.height + 2) cornerRadius:0.f].CGPath;
self.layer.shadowColor = [[UIColor blackColor] CGColor];
self.layer.shadowOpacity = .4f;
self.layer.shadowRadius = 2.0f;
}
In simulator I have next bad result
If I set in Interface Builder size
In simulator all good
I thought that next method must change size of cell, but it change size of item
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(274, 274);
}
So how can I change size of UICollectionViewCell programmatically, without help of Interface Builder?

Is your view controller a UICollectionViewDelegateFlowLayout?
Otherwise sizeForItemAtIndexPath won't get called.
Maybe insert an NSLog inside sizeForItemAtIndexPath to see if it gets called at all.

I find my mistake.
In awakeFromNib I set height of subviews but in
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
forgot update frames of subviews

Related

Change the space between UICollecionViewCell

I have a CollectionView. Here is the implementation for my CollectionView.
- (void)setupCollectionView{
self.flowLayout = [[UICollectionViewFlowLayout alloc] init];
[self.flowLayout setSectionInset:UIEdgeInsetsMake(0, 20, 0, 0)];
self.flowLayout.itemSize = CGSizeMake(150, 35);
self.flowLayout.minimumLineSpacing = 20;
[self.flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.vwCollectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, self.vwQuickReplyContainer.frame.size.width, self.vwQuickReplyContainer.frame.size.height) collectionViewLayout:self.flowLayout];
self.vwCollectionView.backgroundColor = [UIColor clearColor];
[self.vwCollectionView registerNib:[UINib nibWithNibName:#"QuickrepliesCell" bundle:nil] forCellWithReuseIdentifier:#"QuickrepliesCell"];
[self.vwQuickReplyContainer addSubview:self.vwCollectionView];
self.vwQuickReplyContainer.hidden = YES;
[self.vwCollectionView setShowsHorizontalScrollIndicator:NO];
[self.vwCollectionView setDataSource:self];
[self.vwCollectionView setDelegate:self];
[self.vwCollectionView reloadData];
}
Here I set the minimumLineSpacing to set the minimum spacing between successive columns. According to this documentation, I understand that value represents the minimum spacing between successive columns for a horizontally scrolling grid. I was also set the space between my cells. Here is the outcomes of doing that .
But to get more looking good. I want to change my cell's width according to its content's size. So I've updated my cell's frame like this.
- (QuickrepliesCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
self.cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"QuickrepliesCell" forIndexPath:indexPath];
QuickReply *model = [[QuickReply alloc]initWithDictionary:self.quickRepliesArr[indexPath.row] error:nil];
self.cell.lblOpion.text = model.title;
CGFloat width = [self.cell.lblOpion.text sizeWithFont:WWLATOREGULAR(15)].width;
self.cell.frame = CGRectMake(self.cell.frame.origin.x, self.cell.frame.origin.y, width + 24, self.cell.frame.size.height);
return self.cell;
}
Here is the outcomes after updating the cell's width..
I don't know the reason why the space between my cells was changed after changing the cell's size. Can anyone advice on this? thanks.
Instead of setting the itemSize property of the layout to fixed size, implement the collectionView:layout:sizeForItemAtIndexPath: layout delegate method.
Then you can set the proper size of each item.
To achieve it, you need to calculate and change item size in collectionView:layout:sizeForItemAtIndexPath:
- (QuickrepliesCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
self.cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"QuickrepliesCell" forIndexPath:indexPath];
QuickReply *model = [[QuickReply alloc]initWithDictionary:self.quickRepliesArr[indexPath.row] error:nil];
self.cell.lblOpion.text = model.title;
return self.cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
QuickReply *model = [[QuickReply alloc]initWithDictionary:self.quickRepliesArr[indexPath.row] error:nil];
CGFloat width = [model.title sizeWithFont:WWLATOREGULAR(15)].width;
return CGSizeMake(width + 24, 35);
}

set Dynamic width and height of collection view cell

Actually i want to set button dynamically and title of button appear Dynamic i have try this and got width of Dynamic content but am not setting cell width and height.
- (void)viewDidLoad {
[super viewDidLoad];
ContentArray = [[NSMutableArray alloc]init];
self.collectionview.delegate = self;
self.collectionview.dataSource =self;
self.collectionview.backgroundColor = [UIColor clearColor];
[ContentArray addObject:#"Planning"];
[ContentArray addObject:#"Resources"];
[ContentArray addObject:#"Human Resources"];
[ContentArray addObject:#"Agriculture"];
[ContentArray addObject:#"Resources management"];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return ContentArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell * Cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionViewCell"forIndexPath:indexPath];
[Cell.button setTitle:[ContentArray objectAtIndex:indexPath.row] forState:UIControlStateNormal];
return Cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect rect = [[ContentArray objectAtIndex:indexPath.row ] boundingRectWithSize:CGSizeMake(HUGE_VALF, 50) options:NSStringDrawingUsesFontLeading attributes:nil context:nil] ;
return CGSizeMake(rect.size.width, 50);
}
and output is like this
This is perfect i think if i make cell dynamic width and height, so please guide me through this.
pragma mark - GetHeightFromString
- (CGFloat)getTextHeightFromString:(NSString *)text ViewWidth:(CGFloat)width WithPading:(CGFloat)pading FontName:(NSString *)fontName AndFontSize:(CGFloat)fontSize
{
NSDictionary *attributes = #{NSFontAttributeName: [UIFont fontWithName:fontName size:fontSize]};
CGRect rect = [text boundingRectWithSize:CGSizeMake(width, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
//NSLog(#"rect.size.height: %f", rect.size.height);
return rect.size.height + pading;
}
Get height of the string from this method and add this to origional height of your cell or label or button whatever you want to use.
For example:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
YourCellClass *myCell = (YourCellClass*) [collectionView cellForItemAtIndexPath:indexPath];
CGFloat sizeFromString = [self getTextHeightFromString:itemObject.MenuDescription ViewWidth:myCell.frame.size.width WithPading:10 FontName:#"HelveticaNeue" AndFontSize:13];
return CGSizeMake(sizeFromString, sizeFromString);
}
You might need to change the height of inner label too, for this use same method in cellForItemAtIndexPath method of your UICollectionView.
Further more you can customize your own way.
In Swift 2.0:
Using a UICollectionViewFlowLayout enable cell auto-sizing.
The following code inside a UICollectionViewController subclass will enable auto-sizing for it’s flow layout.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let cvl = collectionViewLayout as? UICollectionViewFlowLayout {
cvl.estimatedItemSize = CGSize(width: 150, height: 75)
}
}
You can put different sizes in landscape & portrait mode try this -
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// Adjust cell size for orientation
if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
return CGSizeMake(rect.size.width, 50);
}
return CGSizeMake(rect.size.width, 50);
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[self.collectionView performBatchUpdates:nil completion:nil];
}
you can call invalidateLayout method on the .collectionViewLayout property of your UICollectionView
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[yourCollectionView.collectionViewLayout invalidateLayout];
}
You can try this...
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(width, height);
}
width, height are the dynamically calculated value
Thanks

UICollectionViewCell remove space with animation while scrolling

I have an issue with UICollectionViewCell design layout. I need to remove space with animation while scrolling between UICollectionView Cell, I have try some delegate method of UICollectionView like -
CollectionView - minimumLineSpacingForSectionAtIndex
CollectionView - minimumInteritemSpacingForSectionAtIndex
UIEdgeInsetsMake(0,0,0,0);
scrollViewDidEndDragging
but unable to up to the mark. here is the code:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
float cellWidth = screenWidth / 2.1; //Replace the divisor with the column count requirement. Make sure to have it in float.
CGSize size = CGSizeMake(cellWidth, cellWidth);
return size;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 1.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 1.0;
}
// Layout: Set Edges
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
UIEdgeInsetsMake(0,0,0,0); // after scroll cell space not remove.
}
I didn't completely understand what you're trying to do, but if you want to change layout attributes of a collection view and animate the change, the best way is calling setLayout:animated:.
So like this -
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 1.0;
layout.minimumInteritemSpacing = 1.0;
layout.itemSize = CGSizeMake(cellWidth, cellHeight);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout]
And then whenever you want to change it, just call the setLayout:animated: method:
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout alloc] init];
initialLayout.minimumLineSpacing = 5.0;
initialLayout.minimumInteritemSpacing = 7.0;
layout.itemSize = CGSizeMake(newCellWidth, newCellHeight);
[collectionView setLayout:layout animated:YES];

UICollectionView second page content showing on first page

For some reason, when I'm on the first page of UICollectionView,
it shows the images from the second page.
And I also noticed that the page isn't centered....
I manually set the
pageControl.numberOfPages = 3
So I have three pages of images.
And each page displays 8 items (well...ideally).
This is in ViewDidLoad:
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
[layout setSectionInset:UIEdgeInsetsMake(10, 10, 15, 10)];
[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.collectionView setCollectionViewLayout:layout];
self.collectionView = [[UICollectionView alloc] initWithFrame:keyboardRect collectionViewLayout:layout];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
self.collectionView.pagingEnabled = true;
self.collectionView.alwaysBounceHorizontal = true;
self.collectionView.contentSize = CGSizeMake(keyboardRect.size.width , keyboardRect.size.height);
self.collectionView.showsHorizontalScrollIndicator = false;
UINib *cellNib = [UINib nibWithNibName:#"TopCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:#"cellIdentifier"];
[self.collectionView registerClass:[TopCollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.collectionView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:self.collectionView];
When I tried to increase left and right inset from
[layout setSectionInset:UIEdgeInsetsMake(10, 10, 15, 10)];
It just made things worse. It'd only look okay on the first page,
but then the second and third pages would look off.
And here are some of my code:
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.Images count];
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(70, 70);
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView* )collectionView {
return 3;
}
Thank you in advance!
If you want to show only one section images in each page, then you have to modify
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath method.
You have to return a more generic size.
CGSize returnSize = CGSizeMake(screenWidth / 2 - insets, screenWidth / 2 - insets)
Here inset represents the interItemSpacing for each item. screenWidth is collectionView width.
If you want use the horizontal style of collectionView,you need to custom layout.
Here are some sample code you can use, and I have uploaded custom layout code on github.
FCEmoticonViewLayout *layout = [[FCEmoticonViewLayout alloc]init];
layout.itemSize = CGSizeMake(itemWidht, itemWidht);
layout.itemSpacing = 15;
layout.lineSpacing = 15;
layout.numberOfColumn = 5;
layout.numberOfRow = 2;
self.collectionView.collectionViewLayout = layout;
https://gist.github.com/Heisenbean/a0de38c1379a9d6a83f09ba6cafcb03c

Problems spreading out cells in UICollectionViewFlowLayout

I'm currently trying to space out some custom cells in a UICollectionViewFlowLayout with dynamically sized cells. What I'm finding out is that the spacing in between the cells is inconsistent. I've been reading up on the layout, and I've implemented all the delegate methods to control minimum sizing, but those seem to have no effect. Here is the view as it stands now
And here is my code for sizing:
In the layout and view delegate:
- (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 5;
}
- (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 5;
}
- (CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
Tag *tag = [[Search sharedManager] tagAtIndexPath:indexPath];
NSString *labelText = tag[#"Name"];
CGSize labelTextSize = [labelText sizeWithAttributes:#{NSFontAttributeName: [UIFont systemFontOfSize:8.0f]}];
return labelTextSize;
}
The custom cell
#implementation TagCellCollectionViewCell
- (id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.tagBtn.titleLabel.font = [UIFont systemFontOfSize:8.0f];
self.tagBtn = [UIButton buttonWithType:UIButtonTypeCustom];
// self.tagBtn.frame = CGRectMake(-frame.size.width/4+20, -frame.size.width/4+5, frame.size.width, frame.size.height);
[[self.tagBtn layer] setBorderColor:[[UIColor colorWithRed:234.0f/255.0f green:99.0f/255.0f blue:74.0f/255.0f alpha:1.0f] CGColor]];
[[self.tagBtn layer] setBorderWidth:1.0f];
self.tagBtn.backgroundColor = [UIColor whiteColor];
[self.tagBtn setTitleColor:[UIColor colorWithRed:234.0f/255.0f green:99.0f/255.0f blue:74.0f/255.0f alpha:1.0f] forState:UIControlStateNormal];
[self.contentView addSubview:self.tagBtn];
}
return self;
}
#end
What am I missing here that will put a consistent amount of space between each cell?
The problem here was that the item being returned from
- (CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
was overlapping the minimumInterimSpacing value. Since I was looking for something with systemfontofsize = 8, I needed to ensure that my interim spacing went above that value. Setting it to the 5 I had above caused it to conflict in odd ways, setting it to 15 spaces the cells out evenly because the number of pixels in between the cells is greater than the calculated size.

Resources