uitableview autolayout custom cell causing extra height. Unable to detect where causing the issue while in different project working fine.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
[_stubCell layoutSubviews];
[self configureCell:_stubCell atIndexPath:indexPath];
CGFloat height = [_stubCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 40.f;
}
- (void)configureCell:(CCACustomCell *)cell atIndexPath:(NSIndexPath *)indexPath {
cell.customLabel.text = [_tableData objectAtIndex:indexPath.row];
cell.customLabel.font = [UIFont fontWithName:#"Avenir-Light" size:16.0];
cell.customLabel.textColor = UIColorFromRGB(0x32383B);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
CCACustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
Could you provide details on how are you creating _stubCell?It might be due to some constraint on label.
Have you tried with calculating string height?
+(CGFloat )calculateStringHeight:(NSString *)string WithFont:(UIFont *)font andSidePadding:(CGFloat )padding{
CGRect rect = [string boundingRectWithSize:CGSizeMake([[UIScreen mainScreen]bounds].size.width - (2*padding), 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:font} context:nil];
return rect.size.height;
}
You can return required height for your Label like this. Where you should pass Your description label width in LABEL_DESCRIPTION_WIDTH.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize constrainedSize = CGSizeMake(LABEL_DESCRIPTION_WIDTH , 9999);
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[UIFont fontWithName:FONT_NAME size:FONT_SIZE], NSFontAttributeName,nil];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[_tableData objectAtIndex:indexPath.row] attributes:attributesDictionary];
CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
return requiredHeight;
}
Related
I am using Autolayout and have a customised UITableViewCell that contains UITextView. The height of the cell and text view should be dynamically resized to accomodate larger contents.
Following answers from these links resize ui text view to its content and
dynamic ui text view, I have used a height constraint on the text view and set its value to the height of the content. This does the job of accommodating the textView, but it is overshooting the cell. I have tried options like adjusting the size of the cell also but none of them have helped. Surprisingly, sizeToFit seems to have no effect.
Here is the code I am using:
+ (SongAdditionalTextCell *)resize:(SongAdditionalTextCell *)additionalTextCell{
UITextView *textView = additionalTextCell.additionalText;
CGSize sizeThatFitsTextView = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, MAXFLOAT)];
NSLog(#"content height is %f, frame height is %f", textView.contentSize.height, textView.frame.size.height );
additionalTextCell.addnlTextHeightConstraint.constant = sizeThatFitsTextView.height;
return additionalTextCell;
}
Please see the attached image of the view (text view is second cell). any suggestions appreciated?
I use this one:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 2)
{
NSString *cellText = #"init some text";
CGSize labelSize = [self calculateTextSize:cellText];
return labelSize.height + 20.0f;
}
return 45;
}
- (CGSize) calculateTextSize: (NSString*) text
{
UIFont *cellFont = [UIFont fontWithName:#"HelveticaNeue" size:12.0];
CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f;
CGSize constraintSize = CGSizeMake(width, MAXFLOAT);
CGRect labelRect = [cellText boundingRectWithSize:constraintSize options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:cellFont} context:NSLineBreakByWordWrapping];
CGSize labelSize = labelRect.size;
return labelSize;
}
CGFloat width = CGRectGetWidth(self.tableView.frame) - 40.0f; -
Calculation of the maximum available width of the text, you can use self.view.frame or etc. - 40.0f - because i have indentation from the edge = 20.0f
Try this it working for me
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:#"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10] constrainedToSize:CGSizeMake(255, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height +15;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpletableidentifier=#"simpletableidentifier";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:simpletableidentifier];
if(cell == nil)
{
cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpletableidentifier];
CGSize labelSize = [[[Array objectAtIndex:indexPath.row] valueForKey:#"detail"] sizeWithFont:[UIFont boldSystemFontOfSize:10] constrainedToSize:CGSizeMake(255, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
UILabel *desc=[[UILabel alloc]initWithFrame:CGRectMake(35,2,245,labelSize.height)];
desc.backgroundColor=[UIColor clearColor];
desc.tag=2;
desc.numberOfLines=0;
desc.lineBreakMode=NSLineBreakByWordWrapping;
desc.font=[UIFont boldSystemFontOfSize:10];
desc.textColor=[UIColor whiteColor];
[cell.contentView addSubview:desc];
}
NSString *Str3 = [[Array objectAtIndex:indexPath.row] valueForKey:#"detail"];
UILabel *desc=(UILabel *)[cell.contentView viewWithTag:2];
desc.text=Str3;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
cell.backgroundColor=[UIColor clearColor];
cell.contentView.backgroundColor=[UIColor clearColor];
return cell;
}
Finally figured it out. #RoryMcKinnel's comment does help. Here's what I did in case it can help others. The problem was that I had two type of cells, one where I need to adjust the height (additionalText) and one where I do not need to do that.
In the raw version, I override both estmatedHeightForRowAtIndexPath and heightForRowAtIndexPath and in both methods if the index is for row which is additionalText, I send UITableViewAutomaticDimension else I send the frame height. Of course refinements can be done :) to send better values, but the core concept is same.
here is the code.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.additionalTexts[#((long) indexPath.row)] != nil){
return UITableViewAutomaticDimension;
} else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.additionalTexts[#((long) indexPath.row)] != nil){
return UITableViewAutomaticDimension;
} else return [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainCellIdentifier].frame.size.height;
}
and the resulting screen looks like
I am using Xcode 6 and created a new project and getting issue with autolayout in iOS7 as it is working in iOS8 correctly.
I am using below Code :-
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
UILabel *lbl1=(UILabel*)[cell.contentView viewWithTag:1];
lbl1.text = #"test fkdjsjk kjhsdf ksjh ksjdhf jks kjh kjdhf kjsd h kjh j ,jhfjdfshfk jh fkjsdh fkjs dhkfjhs dkjfh dksjhf jksd hfjkdhs fk jksdhf kjsdh fkjsdh fjkhdsk fjkdsh fkjdsh fkjdsh fkjs djkf djksf kjdshfkjds fkjdsh fkjhs dkjfh kdjs fkdjshfkdsjfh kdjsh fk";
[lbl1 setPreferredMaxLayoutWidth:lbl1.frame.size.width];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
cell.frame = CGRectMake(0.0f, 0.0f, CGRectGetWidth(cell.bounds), CGRectGetHeight(tableView.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
return cell.frame.size.height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
UILabel *lbl1=(UILabel*)[cell.contentView viewWithTag:1];
lbl1.text = #"test fkdjsjk kjhsdf ksjh ksjdhf jks kjh kjdhf kjsd h kjh j ,jhfjdfshfk jh fkjsdh fkjs dhkfjhs dkjfh dksjhf jksd hfjkdhs fk jksdhf kjsdh fkjsdh fjkhdsk fjkdsh fkjdsh fkjdsh fkjs djkf djksf kjdshfkjds fkjdsh fkjhs dkjfh kdjs fkdjshfkdsjfh kdjsh fk";
[lbl1 setBackgroundColor:[UIColor greenColor]];
[cell.contentView setBackgroundColor:[UIColor redColor]];
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
My Requirement is only that label should take height dynamically as content provided to it in iOS 7.
you need to do this .
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGSize constrainedSize = CGSizeMake(self.view.frame.size.width - 30, FLT_MAX);
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"HelveticaNeue" size:14], NSFontAttributeName,
nil];
CGRect requiredHeight = [YourStringObject boundingRectWithSize:constrainedSize
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:attributesDictionary
context:nil];
return requiredHeight.size.height + 20;
}
i use extra 20 for additional padding .
hope this is working for you .
+(CGSize)findTextHeight:(float)height width:(float)width string:(NSString *)desc font:(UIFont*)font{
if ([desc isKindOfClass:[NSNull class]]) {
return 0.0;
}
CGRect textRect =[desc boundingRectWithSize:CGSizeMake(width, height)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil];
CGSize size = textRect.size;
return size;
}
Here you have to give default height or width and label text font. Also set This to your TableView heightForRowAtIndexPath Method..
// Pass the string value for display on label
self.yourLabel.numberofline = 0 // don't forget to set the number of lines zero
+(CGSize)heigtForCellwithString:(NSString *)stringValue
{
//For iPhone
UIFont *font = [UIFont fontWithName:#"Helvetica-Light" size:15];// Here change the font name and font size you have used.
CGSize constraint = CGSizeMake(320,9999);
NSDictionary *attributes = #{NSFontAttributeName: font};
CGRect rect = [stringValue boundingRectWithSize:constraint
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:attributes
context:nil];
return rect.size;
}
CGSize labelHeight = [NSString heigtForCellwithString:#"your text"];
CGRect newFrame = self.yourLabel.frame;
newFrame.size.height = labelHeight.height;
self.yourLabel.frame = newFrame;
I have read alot about dynamic height for UITableViewCell and for the life of me I cannot get it working.
I have a uilabel with dynamic content within a dynamic cell.
I am using the storyboard and have the constraints as so :
I am populating the table using
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"labelCell";
detailTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[detailTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.dynamicLabel.text = sectionString;
return cell;
}
I do not know why everything I have tried has failed. I am thinking it may be the connections on the uiLabel?
This is it , Right :
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0) {
NSString *text = myText;// [myArray objectAtIndex:indexPath.row];
CGSize size;
if (SYSTEM_VERSION_LESS_THAN(#"7.0")) {
// code here for iOS 5.0,6.0 and so on
CGSize fontSize = [text sizeWithFont:[UIFont fontWithName:#"Helvetica" size:17]];
size = fontSize;
}
else {
// code here for iOS 7.0
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Helvetica Neue" size:19], NSFontAttributeName,
nil];
CGRect fontSizeFor7 = [text boundingRectWithSize:CGSizeMake(571, 500)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
size = fontSizeFor7.size;
}
NSLog(#"indexPAth %ld %f",(long)indexPath.section, size.height);
return size.height +30 ;
}
Finally, at the delegate of cellForRowAtIndexPath: don't forget to make the UILabel flexible for text :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// ........
cell.dynamicLabel.text = sectionString;
cell.dynamicLabel.numberOfLines = 0;
return cell;
}
I would like the UITableView's row height to respond to changes in the user's preferred text size. For example, when the preferred text size increases, I would like to increase the row height by a proportional amount. Here's what I have so far:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
// observe when user changes preferred text size
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(preferredContentSizeChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil];
}
- (void)preferredContentSizeChanged:(NSNotification *)notification
{
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
// leverage Text Kit's Dynamic Type
cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
cell.textLabel.text = #"All work and no play...";
return cell;
}
So what's the best way to calculate a row height that reflects the user's preferred text size?
I have recently accomplished this and found it to be very simple. Instead of using sizeWithFont: you should use the new boundingRectWithSize:options:attributes:context method in iOS 7.
Set up your table view cell as usual and specify the preferredFontForTextStyle: on your text label as such:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableViewCellIdentifier forIndexPath:indexPath];
//set your table view cell content here
[[cell textLabel] setText:#"Lorem ipsum dolour sit amet."];
[[cell textLabel] setNumberOfLines:0];
[[cell textLabel] setLineBreakMode:NSLineBreakByWordWrapping];
[[cell textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];
return cell;
}
Then to correctly determine the size of the text label, evaluate the boundingRectWithSize:options:attributes:context to calculate the required height.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//add your table view cell content here
NSString *string = #"Lorem ipsum dolor sit amet.";
NSDictionary *attributes = #{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleBody]};
CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
return ceilf(CGRectGetHeight(frame);
}
You may want to subclass your table view cell also to listen for UIContentSizeCategoryDidChangeNotification notifications at which point you can update your UI when the user changes their preferences in Settings.app
- (void)contentSizeCategoryDidChangeNotificationHandler:(NSNotification *)notification
{
[[self textLabel] setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]];
}
Should you require additional padding around the text label, you can define a constant value such as
static CGFloat const TableViewCellPadding = 10.0;
With this in place, you can either add a constant value to the value returned from tableView:heightForRowAtIndexPath:
return (ceilf(CGRectGetHeight(frame) + TableViewCellPadding);
Or you could inset the frame returned from boundingRectWithSize:options:attributes:context as such:
CGRect frame = [string boundingRectWithSize:CGSizeMake(CGRectGetWidth(tableView.bounds), CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
frame = CGRectInset(frame, 0.0, TableViewCellPadding);
use this method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *fieldLabel = labelCell.textLabel.text;
CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:#"Georgia" size:17.0f] constrainedToSize:CGSizeMake([UIScreen mainScreen].bounds.size.width-20, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
float newHeight = textSize.height+22.0f;
return newHeight;
}
Add below code to cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
UILabel *lblfield=[[UILabel alloc] init];
NSString *fieldLabel=[NSString stringWithFormat:#"%#",labelCell.textLabel.text];
CGSize textSize = [fieldLabel sizeWithFont:[UIFont fontWithName:#"Georgia" size:17.0f] constrainedToSize:CGSizeMake([UIScreen mainScreen].bounds.size.width-20, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
float newHeight = textSize.height+22.0f;
lblfield.frame=CGRectMake(10, 0, [UIScreen mainScreen].bounds.size.width, newHeight);
lblfield.backgroundColor=[UIColor clearColor];
lblfield.text=strusername;
[cell addSubview:lblfield];
return cell;
}
For some strange reason the TableView Cells are not fitting the dynamic textual content properly. They should have a slight margin between the top and bottom of cell. Unfortunately, depending on the amount of textual content, some cells have no top and bottom margin(tightly packed) and others have huge margins.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
float result = 30;
if (indexPath.section != 0){
CGSize size = [[self textForIndexPath:indexPath isTitle:NO] sizeWithFont:kITDescriptionFont constrainedToSize:CGSizeMake(220, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
result = MAX(result, size.height);
}
return result;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *doubleCellIdentifier = #"ITDoubleDetailCEllIdentifier";
static NSString *cellIdentifier = #"ITDetailCEllIdentifier";
NSString *cellIdent = (indexPath.section == 0)? doubleCellIdentifier : cellIdentifier;
ITDescriptionCell *cell = (ITDescriptionCell *)[tableView dequeueReusableCellWithIdentifier:cellIdent];
if (!cell) {
UITableViewCellStyle style = (indexPath.section == 0)? UITableViewCellStyleValue2 : UITableViewCellStyleDefault;
cell = [[ITDescriptionCell alloc] initWithStyle:style reuseIdentifier:cellIdent];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.textLabel setNumberOfLines:0];
[cell.textLabel setFont:kITDescriptionFont];
}
else {
[cell.textLabel setText:#""];
[cell.detailTextLabel setText:#""];
}
[cell sizeToFit];
return cell;
}
You need to dynamically calculate the height of your text and based on that and the padding you want, adjust the height of the cell through the following delegate method:
#define PADDING 10.0f
- (CGFloat)tableView:(UITableView *)t heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Subscription *sub = [_dictTask valueForKeyPath:#"subscription"];
NSArray *meta = sub.meta.allObjects;
NSString *text = [[meta objectAtIndex:indexPath.row] valueForKey:#"sum_value"];
CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(self.tableView.frame.size.width - PADDING * 3, 1000.0f)];
return textSize.height + PADDING * 3;
}