UItableviewcontroller SizeToFit not working on UILabel field - ios

Hi I am using sizetofit on my UILabel field, it works fine when I load the tableview controller, but then starts cutting of letters and wrapping to another line when I scroll up and down. Here is the code I use in CellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"subjectCell" forIndexPath:indexPath];
// Configure the cell...
// Load and display subject photo image
UIImageView *subjectImageView = (UIImageView *)[cell viewWithTag:200];
subjectImageView.image = [UIImage imageNamed:subjectImages[indexPath.row]];
// Load and display subject label
UILabel *subjectLabel = (UILabel *)[cell viewWithTag:201];
subjectLabel.text = [subjectItems objectAtIndex:indexPath.row];
[subjectLabel sizeToFit];// call this to fit size of the label according to text
return cell;
}
And here is a screen shot of my tableviewcontroller originaly loaded:
And here after scrolling up and down you can see the descriptions have been cut
Thanks for any help you can give to solve this.
Cheers
Carson

Using sizeToFit for UILabel can cause a mess like this in UITableView with reusing cells. One of solutions I can think of is to set the width of the frame for your label width before you call sizeToFit and you have to do this every time you assign text to the label. It should look something like this:
CGRect frame = subjectLabel.frame;
frame.size.width = 100.0; //try to adjust this value
subjectLabel.frame = frame;
[subjectLabel sizeToFit];

Related

How to add Constraints programmatically to default imageView and textLabel of UITableViewCell

I am currently creating my cell like this
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.imageView.image = [UIImage imageNamed:image];
cell.imageView.tintColor = [UIColor whiteColor];
cell.textLabel.text = #"Push me";
cell.textLabel.textColor = [UIColor whiteColor];
cell.userInteractionEnabled = YES;
return cell;
Everything is working fine but some of my text which is long gets truncated at the end. How can i avoid that?? I don't want to set the numberOfLines property.
Is there a way i can arrange my imageView and textlabel a bit via constraints so that my text looks fine. I tried adding constraints to contentView of cell but that make my cell all weird.
I am new to iOS development and learning. Any help will be greatly appreciated.
If you don't want to set numberOfLines. adjustsFontSizeToFitWidth property will set your content bound to width without truncating it. but it will decrease font size if required.
cell.textLabel.adjustsFontSizeToFitWidth = true
There is no need to add constraint programmatically,
Step 1 - Drag and drop the cell on UITableview
Step 2 - Design your cell with image view and label , use constraints
Step 3 - Create CustomCell.h and CustomCell.m file which will be inherited from UITableViewCell
Step 4 - create IBOutlet for image view and label in CustomCell.h
Step 5 - In your ViewController -
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
cell.textLabel.text = [self.dataAraay objectAtIndex:indexPath.row];
return cell;
}
https://www.raywenderlich.com/129059/self-sizing-table-view-cells
UIImageView *imgarrow=[[UIImageView alloc]init ];
imgarrow.frame=CGRectMake(230,2, 27, 27);
imgarrow.image=[UIImage imageNamed:#"check_mark#2x.png"];
[cell addSubview:imgarrow];
//write same code for UILabel
//change rectmake values

dynamically sized UITableViewCell with UILabel's text being cut off after one line

Im trying to implement dynamically sized tableView cells. The cells have a UILabel (among other things) that holds a variable amount of text. Before I customized the cell I was just using cell.textLabel.text to set the text and the cell resized fine and all the text was shown. I did not have to mess with the label at all. But now I have a custom UILabel inside my cell and the text is being cut off. Ive looked at a lot of answers on here but nothing seems to be working.
Here is my code:
//This method gets the size of the text that will be inside the cell/label. This works fine
-(CGFloat)getLabelHeightForText:(NSString *)text andWidth:(CGFloat)labelWidth
{
CGSize maximumSize = CGSizeMake(labelWidth, 10000);
UIFont *systemFont = [UIFont systemFontOfSize:15.0];
//provide appropriate font and font size
CGSize labelHeightSize = [text sizeWithFont:systemFont
constrainedToSize:maximumSize
lineBreakMode:NSLineBreakByWordWrapping];
return labelHeightSize.height;
}
//Dynamically changes the cell height. This works fine
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *reviewText = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
CGFloat textHeight = [self getLabelHeightForText:reviewText andWidth:self.tableView.frame.size.width];
return (textHeight + 40);
}
//This is what doesnt seem to be working.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//Review label
NSString *reviewText = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
UILabel *reviewLabel = (UILabel *)[cell viewWithTag:102];
CGFloat reviewLabelHeight = [self getLabelHeightForText:reviewText andWidth:reviewLabel.frame.size.width];
reviewLabel.frame = CGRectMake(reviewLabel.frame.origin.x, reviewLabel.frame.origin.y, reviewLabel.frame.size.width, reviewLabelHeight);
reviewLabel.text = reviewText;
reviewLabel.numberOfLines = 0;
reviewLabel.lineBreakMode = NSLineBreakByWordWrapping;
NSLog(#"Height: %f", reviewLabel.frame.size.height);
NSLog(#"Width: %f", reviewLabel.frame.size.width);
// cell.textLabel.text = [[self.reviews objectAtIndex:indexPath.row] objectForKey:#"reviewText"];
//
// cell.textLabel.numberOfLines = 0;
//
// cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
return cell;
}
As you can see, ive logged the height and width of the label. The width stays a constant 280 which is correct and the height changes dynamically depending the text. Everything looks as if it should be working fine. But sadly it doesnt. The cell resizes fine. The label (judging from the NSLogs) seems to resize fine, so why does my text get cut off?
Thanks
I have currently resolved this by adding some autolayout constraints to my prototype cell. Turning off autolayout also worked.

Adjusting elements and the height of UITableView on scroll

I have a UITableView with multiple UILabels. The issue is that the text in these cells change dynamically as I receive data from the server. It works fine when I load the view controller. But as I scroll, the height of the cells are not updated as heightForRowAtIndexPath is only called once.
Here are the screenshots:
As I've shown in the screenshot, the question label reduces in size which leads to a gap (shown by arrow).
Here's my cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIndentifier = #"CustomCell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIndentifier];
if (cell == nil)
{
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndentifier];
}
cell.question.autoDetectLinks = YES;
// Used to populate cell from NSDictionary
[self setDataToCell:cell AtIndexPath:indexPath];
return cell;
}
Here's my custom cell's layoutSubviews:
- (void) layoutSubviews
{
CGRect frame = self.question.frame;
frame.size.width = 277.0f; //you need to adjust this value
self.question.frame = frame;
self.question.numberOfLines = 2;
[self.question sizeToFit];
// Place time below question
CGRect timeFrame = self.time.frame;
timeFrame.origin.y = self.question.frame.origin.y + self.question.frame.size.height + 5;
self.time.frame = timeFrame;
[self.time sizeToFit];
}
So to tackle this situation I called
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[_tableIndexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
in - (void) scrollViewDidScroll:(UIScrollView *)scrollView
This solves my problem but reduces the performance and the elements jump around before settling even after setting the animation as UITableViewRowAnimationNone. Is there a better way of doing it? Should I call reloadRowsAtIndexPaths somewhere else?
Thanks.
Ok here come the edited answer:
The problem is your sizeToFit in your layoutSubviews. Just follow this link to resolve your issue:
here
If you also want the cell and the label to dynamically resize to their corresponding text but at the same time your timelabel to be directly underneath it you will have to determine the size of your uilabel based on the text, font and font-size.
See here for more information:
here

UITableView with UILabel SizeToFit get mess when Scrolling

Hi everyone I have problem with my tableview, i make Cell with uilabel with SizeToFit and then calculate the UILabel Height for set the cell Height everything work well except when i scrolling my tableView the text get weird like one char per line:
My TableViewVell Method is:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
UILabel *label = (UILabel *)[cell viewWithTag:1];
label.text = [someArray objectAtIndex:indexPath.row];
// Set the UILabel to fit my text;
messageLabel.lineBreakMode = UILineBreakModeWordWrap;
messageLabel.numberOfLines = 0;
[messageLabel sizeToFit];
return cell;
}
The Cell Height stay in the correct Size the problem only with the UILabel ...
this the result when i load the view:
First screenshot
And this is after i start scroll the TableView:
Second screenshot
Any Help???
The method sizeToFit respects the width of the frame and adjust the height. And table view cell reuse the cells. Combining those two behaviors can cause the issue you described.
One of your label, which is very short in content (e.g. in the 4th cell with the word "jio"), is resized with sizeToFit and the resulting width is smaller than the original width you intended.
After that, table view reuse the cell and sizeToFit still respects the small width calculated from previous call of sizeToFit.
Solutions:
1) set the width of the frame to your original intended label width everytime before you call sizeToFit:
CGRect frame = messageLabel.frame;
frame.size.width = 100.0; //you need to adjust this value
messageLabel.frame = frame;
2) use your row height calculation and set the frame height instead. No need to use sizeToFit.
you should probably subclass your cell and clean the UILabel on
override func prepareForReuse() {
super.prepareForReuse()
self.label.text = nil
}
This might help
http://www.cimgf.com/2009/09/23/uitableviewcell-dynamic-height/
The approach in given reference and solution provided by #Verbumdei is nearby same.
If you are not using autolayout, this can also be solved by adding a category on UIView
public func sizeToFit(constrainedSize: CGSize) -> CGSize {
var newSize = sizeThatFits(constrainedSize)
newSize.width = min(newSize.width, constrainedSize.width)
newSize.height = min(newSize.height, constrainedSize.height)
self.size = newSize
return newSize
}
The idea is to use sizeThatFits with a constrained size to determine the size to adopt and then use the min expected width/height.
Then you just have to do something like
yourLabel.sizeToFit(self.contentView.size) // or
yourLabel.sizeToFit(CGSize(width: maxWidth, height: self.contentView.size.height))
You can set preferred Width property of label. That worked for me
preferred Width

UILabels not resizing in UITableView

I have a UITableView that uses prototype cells. The cells have a custom class called dataCell. The custom cells also have three UILabels:idLabel, contLabel, and expLabel. The cells properly resize based on the amount of text in expLabel; however, I cannot get the label itself to resize. Some labels resize when I scroll down; however, they also revert to showing only two lines and omitting text when I scroll back up. Here is my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
dataCell *cell = (dataCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// the rest of your configure cell
// First Cell Label
[cell.idLabel setText:[idData objectAtIndex:indexPath.row]];
cell.idLabel.numberOfLines = 0;
// Second Cell Label
[cell.contLabel setText:[conData objectAtIndex:indexPath.row]];
cell.contLabel.numberOfLines = 0;
// Third Cell Label
[cell.expLabel setText:[expData objectAtIndex:indexPath.row]];
cell.expLabel.numberOfLines=0;
CGSize expectedLabelSize = [cell.expLabel.text sizeWithFont:cell.expLabel.font constrainedToSize:CGSizeMake(220, FLT_MAX) lineBreakMode:cell.expLabel.lineBreakMode];
cell.expLabel.frame=CGRectMake(cell.expLabel.frame.origin.x, cell.expLabel.frame.origin.y, expectedLabelSize.width, expectedLabelSize.height);
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
dataCell *cell = (dataCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
CGSize maximumLabelSize = CGSizeMake(220, FLT_MAX);
[cell.expLabel setText:[expData objectAtIndex:indexPath.row]];
CGSize expectedLabelSize = [cell.expLabel.text sizeWithFont:cell.expLabel.font constrainedToSize:maximumLabelSize lineBreakMode:cell.expLabel.lineBreakMode];
if (expectedLabelSize.height<43) {
expectedLabelSize.height=43;
}
return expectedLabelSize.height; }
Any help would be much appreciated
If you are using a storyboard and a UITableViewCell then you can just change the auto resizing mask, but if you are doing it programmatically then you will have to set the calculate the text width and height and reset the frame of the labels,
UILabel* label = [[UILabel alloc] init];
UIFont* font = label.font;
CGSize maxContentSizeForText = CGSizeMake(maxTextWidth, maxTextHeight);
CGSize stringTextSize = [string sizeWithFont:font constrainedToSize:maxContentSizeForText lineBreakMode:NSLineBreakByWordWrapping];
[label setFrame:CGRectMake(xPosition, yPosition, stringTextSize.width, stringTextSize.height);
[label setNumberOfLines:1000];
your label is probably a property from a xib file or storyboard, and the number of lines is just saying that you want the label to get really really big, since we can't say "infinite" i just generally use 1000 indicating 1000 lines of text maximum

Resources