I have a view which contains UICollectionView that loads external cellnib file of UICollectionViewCell. I have the data showing properly just the way I want. I want to keep the cell height based on the textlabel inside it but I am not sure what am I missing in the code below. I have tried going through answers but it did not make much sense on how to tackle it. Please help. Thanks in advance.
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#" mycell" forIndexPath:indexPath];
NSString *string = cell.lblContact.text;
CGSize size = [self getLabelSize:string];
NSLog(#"%f and %f",size.width ,size.height);
return cell;
}
- (CGSize)getLabelSize:(NSString *)string {
UIFont *updatedFont = [UIFont fontWithName:#"myFont" size:18.0];
CGRect rect = [string boundingRectWithSize:(CGSize){maxWidth, CGFLOAT_MAX} options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName: updatedFont } context:nil];
return rect.size;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize retval = CGSizeMake(collectionView.frame.size.width, 75);
return retval;
}
- (UIEdgeInsets)collectionView: (UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
I found the solution. I created a string in sizeForItemAtIndexPath that was getting a value out from the same place as cell.lblContact.text.
MyObject *mc = (MyObject *) [contactArray objectAtIndex:indexPath.row];
NSString *myString = mc.contactName;
CGSize size = [self getLabelSize:myString];
NSLog(#"%#", myString);
NSLog(#"%f", size.height);
if (myString.length > 25) {
CGSize retval = CGSizeMake(collectionView.frame.size.width, size.height);
[collectionView layoutIfNeeded];
return retval;
} else {
CGSize retval = CGSizeMake(collectionView.frame.size.width, 75);
return retval;
}
You retrieve the size of the label, but it looks like you are using a different CGSize to size the label. Instead of CGSizeMake(collectionView.frame.size.width, 75), try keeping a reference to the size of the label and using that as the return value:
- (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MyCollectionViewCell *cell = (MyCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#" mycell" forIndexPath:indexPath];
NSString *string = cell.lblContact.text;
self.labelSize = [self getLabelSize:string];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return self.labelSize;
}
EDIT
Have you tried accessing the frame of the label and storing it?
self.labelSize = CGSizeMake(self.myCell.frame.size.width, self.myCell.frame.size.height);
Related
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
I have one Image and one Label. Image is fix but the label is variable.
So, the size of the label may vary.
So, i want to change the height of the cell.
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return questions.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
SymbolCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
Question *q = [questions objectAtIndex:indexPath.row];
NSString *image = q.ImageName;
cell.imgSymbol.image = [UIImage imageNamed:image];
cell.lblName.text = q.Answer;
return cell;
}
Use this method to return cell width and height.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
SymbolCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
Question *q = [questions objectAtIndex:indexPath.row];
NSString *image = q.ImageName;
cell.imgSymbol.image = [UIImage imageNamed:image];
cell.lblName.frame = CGRectMake(cell.lblName.frame.origin.x , cell.imgSymbol.frame.origin.y+8, cell.lblName.frame.size.width, 21);
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:q.Answer];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:NSMakeRange(0, str.length)];
cell.lblName.attributedText = str;
[cell.lblName setNumberOfLines:0];
[cell.lblName sizeToFit];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// calculate label height here
Question *q = [questions objectAtIndex:indexPath.row];
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:q.Answer];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:NSMakeRange(0, str.length)];
CGSize sizeName = CGRectIntegral([str boundingRectWithSize:CGSizeMake("YorLabel Width", MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil]).size;
// give here cell width and height
return CGSizeMake((collectionView.frame.size.width-20)/3, sizeName.height+YourImage height + spec); // here return your cell height
}
I'm trying to adjust the cell heights to fit the UIImages, the problem is it does not seem like the UIImage is filling the collectionView cell. As you can see on this
Image: http://oi61.tinypic.com/98d3zd.jpg
It seems like the cell adjusted, but the image is not filled correctly to fill the cell?
cellheights
First I've created a loop which calculate the new height if the cellWidth is 140, which is the case allways.
for (int i = 0; i < [homesDic count]; i++) {
UIImage *originalImage = [[homesDic objectAtIndex:i] objectForKey:#"image"];
CGFloat originalHeight = originalImage.size.height;
CGFloat originalWidth = originalImage.size.width;
CGFloat wantedWidth = 140;
float wantedHeight = (originalHeight*wantedWidth)/originalWidth;
[_cellHeights addObject:#(wantedHeight)];
}
Then I insert a imageView in to the collectionView cell and set the frame and set cell height equal to the imageheight from the cellHeights array.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FRGWaterfallCollectionViewCell *waterfallCell = [collectionView dequeueReusableCellWithReuseIdentifier:WaterfallCellIdentifier indexPath];
waterfallCell.lblTitle.text = [NSString stringWithFormat: #"Item %d", indexPath.item];
waterfallCell.bottomView.backgroundColor = [UIColor colorWithRed:0.184 green:0.192 blue:0.196 alpha:0.7];
waterfallCell.homeImage.image = [[homesDic objectAtIndex:indexPath.item] objectForKey:#"image"];
waterfallCell.homeImage.frame = CGRectMake(0, 0, [self.cellHeights[indexPath.item] floatValue], waterfallCell.frame.size.width);
return waterfallCell;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(FRGWaterfallCollectionViewLayout *)collectionViewLayout
heightForItemAtIndexPath:(NSIndexPath *)indexPath {
return [[self.cellHeights objectAtIndex:indexPath.item] floatValue];
}
To set up cell size you should use collectionView:layout:sizeForItemAtIndexPath method, try this:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
// Get reference to your image base on indexPath here (I assume you have one section and indexPath.row refer to right image) adjust if needed:
UIImage *originalImage = [[homesDic objectAtIndex: indexPath.row] objectForKey:#"image"];
CGSize imgSize = originalImage.size;
//Adjust if needed
imgSize.height += 20;
imgSize.width += 20;
return imgSize;
}
if you need spacing between the cells, headers, and footers, use this method:
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(20, 10, 20, 10);
}
Hope this is what you are looking for
I am using a UICollectionView with 2 columns in it. i have a requirement to resize (expand) a cell when it is tapped. Im using the following bit of code which seems to be working except that the whole row gets expanded instead of a single cell... Im sure there must be a way to avoid using UICollectionView,dont want to use two seperate tableviews just coz of this minor problem..
PFB the code that im using to adjust the size of the cell..
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize itemSize;
if([self.selectedOrder isEqual:indexPath]) {
NSLog(#"coming");
itemSize = (CGSize ){.width = 330, .height = 150};
}
else {
itemSize = (CGSize ){.width = 330, .height = 75};
}
return itemSize;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if([self.selectedOrder isEqual:indexPath]) {
self.selectedOrder = [NSIndexPath indexPathForItem:-1 inSection:-1];
}
else {
self.selectedOrder = indexPath;
}
[collectionView performBatchUpdates:^{
// append your data model to return a larger size for
// cell at this index path
// [collectionView invalidateIntrinsicContentSize];
[collectionView.collectionViewLayout invalidateLayout];
[collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
} completion:^(BOOL finished) {
}];
}
Im using UICollectionView for my project. But i get some issue with it: cellForItemAtIndexPath is not working when i call reloadData and scroll. This is my code:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [listImage count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView1 cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"indexpath %d", indexPath.row);
NSString *cellIdentify = #"HomeCollectionViewCell";
HomeCollectionViewCell *cell = (HomeCollectionViewCell *)[collectionView1 dequeueReusableCellWithReuseIdentifier:cellIdentify forIndexPath:indexPath];
NSMutableDictionary *dictionary = [listImage objectAtIndex:indexPath.row];
//set image pop-up for first time login
UIImageView *imageViewSignUp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon_popupSignUp.png"]];
if (indexPath.row == 5 && ![IQUser currentUser]) {
imageViewSignUp.frame = CGRectMake(120, self.view.frame.size.height-100, 60, 63);
[self.view addSubview:imageViewSignUp];
}
//set data for product or share
[cell.contentView setUserInteractionEnabled:YES];
NSString *string = [[dictionary objectForKey:kDetail] objectForKey:kImage];
if ([string rangeOfString:#"http://"].location != NSNotFound) {
[self setImageWithString:cell.imageView aURL:string];
} else {
cell.imageView.image = [UIImage imageNamed:string];
}
return cell;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
}
-(CGSize)collectionView:(UICollectionView *)collectionView1 layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGSize size = collectionView.frame.size;
return size;
}
-(void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
}
it is a issue on collectionView?!
What is not working with UICollectionView ? please specify your problem.
And why are you setting image on UIView in cellForItemAtIndexPath
UIImageView *imageViewSignUp = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon_popupSignUp.png"]];
if (indexPath.row == 5 && ![IQUser currentUser]) {
imageViewSignUp.frame = CGRectMake(120, self.view.frame.size.height-100, 60, 63);
[self.view addSubview:imageViewSignUp];
}