I have created a couple of different UITableViewCells for my tableViewController, this is because I have different bits of data I want to display depending what comes back. Because of this each UITableViewCell is of a different height.
This is all fine, However one of my UILabels has to display a large NSString, so large that I have had to word wrap it onto a second line, The only issue here is that it messes up my UITableViewCell formatting.
My question is, is it possible to flag or capture some type of action when a UILabel receiving a NSString has to use wordrap because the size of the NSString is too long?
Or is there a way to calculate the physical length (not how many chars are in the string) of the NSString so I can decide hey I need to reformat my UITableViewCell..
Any help would be greatly appreciated.
The usual way is to use sizeWithFont:constrainedToSize:lineBreakMode: to get the size of a string. You use it like this:
CGSize stringSize = [theString sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:12] constrainedToSize:CGSizeMake(320, 3000) lineBreakMode:NSLineBreakByWordWrapping ];
This is set for the full width of a table cell, but you would want to use the width of your label instead.
i dont know if i understand well but you have the height of your tableviewcell right? and you have a NSString maybe in a UITextView and this height of content of textview is higher then tableviewcell. Well, you should first calculate the content of UITextview, add into a list and when heightforRowAtindexPath was called, you should calculate new height (content textview) plus something... And to solve the max length you should count a limit for chars or limit for lines..
Some usefull code:
//resize height with content of UITextView
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;
//delegate textview to calculate limit for text.
- (void)textViewDidChange:(UITextView *)textView{
NSInteger restrictedLength=140;
NSString *temp=textView.text;
if([[textView text] length] > restrictedLength){
textView.text=[temp substringToIndex:[temp length]-1];
}
}
remember, you need to calculate the limit/size content from UITextview before heightforRowAtIndexPath called. When it called you already need to know your max height for cell.
Related
I am using UITableViewAutomaticDimension for dynamic height of cells of a UITableview. Everything works fine when I set plain text in the label inside the UITableviewCell.
Problem occurs with the cell height when I set plain text along with emoji characters in the label. The cell height do increase dynamically but the height is wrong due to emoji characters. I think UITableview may be considering the unicode as a text instead of emoji icon hence it returns only plain text height.
In my case label's x origin is also dynamic.
Please see the below screen shots for the problem occurring,
Any suggestions?
Remove UITableViewAutomaticDimension, calculate height of label dynamically by below given methods and manage cell height accordingly.
//--- Calculate Height Of String ---//
+(CGFloat)textHeight:(NSString*)text withFont:(UIFont*)font andMaxWidth:(CGFloat)maxWidth
{
CGFloat maxHeight = 99999;
CGSize maximumLabelSize = CGSizeMake(maxWidth,maxHeight);
NSDictionary *attributes = #{NSFontAttributeName: font};
CGRect expectedLabelSize = [text boundingRectWithSize:maximumLabelSize options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attributes context:nil];
return expectedLabelSize.size.height;
}
I am working on Tableview with dynamic cell height.
Due to my requirement, i have to show 40 types of different cell.Each cell is different.
For ex.
one cell having 2 labels,1 imageview
another cell having only 2 imageview
another cell having 5 labels,1 textview,2 buttons, 2 imageview
My problem is i cant able to define the height statically.ie. labels and textview in each cell is based on the text at run time.So according to the individual elements i need to adjust the height.So i have calculated the label and textview height based on below coding,
CGSize constrainedSize = CGSizeMake((IS_IPAD)?765:285 , 9999);
NSDictionary *dict=[array objectAtIndex:indexPath.row];
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Lucida Sans" size:(IS_IPAD)?18.0:12.0], NSFontAttributeName,
nil];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[dict valueForKey:#"response"]attributes:attributesDictionary];
CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
return requiredHeight.size.height;
The above code works fine.But it's little bit difficult to calculate for 5-10 labels for a cell.Because i need to call 10 times for every cell.So it causes slow scrolling on tableview.Also after that i need to change every label/textview and imageview's y position frame.Is there any alternate to achieve this? Any help would be highly appreciated.
Thanks.
Initially set a placeholder height for all your cells. later try to reload cells with exact heights.
Write a method that is capable of calculating the approx height for a specific cell. And pass some parameters into it.
I've done a lot of reading already on this, but it's seems like there's no simple solution.
I'm trying to make an app that loads an NSArray of NSString comments to display in a UITableView. The comments all vary in size.
How can I get the cell to adjust its size to show the entire content of each comments?
I'm trying to find a simple solution without resorting to using magic CFloat numbers.
Is there a method in apple's API that allows me to calculate the needed height of the cell.detailTextLabel given an NSString comment and fixed width?
I think if I can calculate this height, all that's need is to set the height of the cell and the height of the row.
Not really sure what order to do this in since I've read the cell hasn't been created yet when heightForRow:AtIndexPath: gets called.
Calculate the height of the text in tableView:heightForRowAtIndexPath:
You need to use boundingRectWithSize:options:context: on iOS 7+ and sizeWithFont:forWidth:lineBreakMode: on iOS 6 and below. See the apple documentation for more information.
UIFont *font = [UIFont oka_commentLabelFont];
NSString *text = [self commentForIndexPath:indexPath];
CGFloat cellWidth = 300.f;
CGSize boundingSize = CGSizeMake(widthForCell, CGFLOAT_MAX);
CGSize size;
if ([text respondsToSelector:#selector(boundingRectWithSize:options:attributes:context:)]) {
size = [text boundingRectWithSize:boundingSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{ NSFontAttributeName : font }
context:nil].size;
} else {
size = [text sizeWithFont:font
constrainedToSize:boundingSize
lineBreakMode:NSLineBreakModeWordWrap];
}
return size.height;
You need to set the font to the same font you want to use on the cell. If you put this in a performUpdates block on the tableView then you will get a nice expanding animation.
Don't set the height of the cell, set the height of the row and the table view will do the rest.
To calculate the height of the text, ask a label with textRectForBounds:limitedToNumberOfLines:, or ask the string with one of the many methods like sizeWithFont:constrainedToSize:lineBreakMode:.
You may need to deal with padding around the label when compared to the size of the cell.
yes we can calculate the height of UILabel depending on the Font and line break mode.
UIFont * font = [UIFont systemFontOfSize:12.0];
CGSize newSize = [text sizeWithAttributes:#{NSFontAttributeName:font}];// You can add other attributes in dictionary to like line break mode.
Here you got new size for the text which will be in UILabel, now in hegihtForCellAtIndexPath method you can change the size of UITableViewCell. newSize.height is height you need for label, now you can add some value to it for offsets and return it.
Use
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
In my case, how would I resize a UITableViewCell to accomodate the height of a UITextView that it contains?
I'm currently trying to achieve this using the following code:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// init the font that we use
UIFont *font = [UIFont fontWithName:#"SourceSansPro-Regular" size:16];
if (indexPath.section == 0) {
// get the text size of the thread
CGSize textSize = [_thread.text sizeWithFont:font constrainedToSize:CGSizeMake(280, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
return textSize.height + 20;
}
// default
return 60;
}
I feel like if I could just get access to the UITableViewCell in this method, then I could use the contentSize property of the UITextView in it, and return that. But I don't think that's possible at this point in the execution flow.
I can't just tweak that buffer, because it doesn't scale with the text size being returned by the get size function. The shorter the text, the more visible a larger buffer size is.
This is adjusting the height of the UITableViewCell, but it's not showing all of the UITextView inside of it. I've specified the width of the UITextView in the sizeWithFont:constrainedToSize:lineBreakMode: method, which is 280. I've specified that I wish to have essentially no maximum height, so that it can word-wrap as much as it needs to, using the CGFLOAT_MAX constant. I append a buffer of 20 units to the resulting height of the method call, because there is a 20 unit buffer above the UITextView, in my Storyboard, and I'd like to also have a 20 unit buffer below it.
The end result of all of this still has text being clipped off, though. Here is a picture of what I am talking about:
Any ideas?
I'm going to go ahead and answer my question. The answer to this comes in two steps.
First, adjust the size of the UITextView during your logic inside of the tableView:cellForRowAtIndexPath: method. Make sure to do this after making any changes to the text in the UITextView. I re-size my UITextView using the following method, inside of a subclass of UITableViewCell where self.text is the text view:
- (void)resizeTextView {
// get the current frame size
CGRect frame = self.text.frame;
// set it to the height of the text view
frame.size.height = self.text.contentSize.height;
// set the new size of the text view
self.text.frame = frame;
}
Next, I specify the height of the UITableViewCell inside of the tableView:heightForRowAtIndexpath: method. This is where most of the mystery exists, because to get the height for this row you have to calculate the height of any text that is going to be displayed in the row, along with anything else you need to calculate the height of. In my scenario, is was a UITextView. Without access to the UITableViewCell instance in this method, you're forced to use something like sizeWithFont:constrainedToSize:lineBreakMode:. But, I noticed this was not returning consistent heights for me. Or at least, not heights that seemed to make enough room for my text from the UITextView. That was the problem, though. The text view has additional left and right padding as well as different line heights, or something, than the sizeWithFont method uses.
So, after fudging the results of the sizeWithFont method for awhile, I ended up with the following code:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// init the font that we use
UIFont *font = [UIFont fontWithName:#"SourceSansPro-Regular" size:16];
if (indexPath.section == 0) {
// get the text size of the thread
CGSize textSize = [_thread.text sizeWithFont:font constrainedToSize:CGSizeMake(280 - 16, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
// text height + padding
return textSize.height + 40;
} else if (indexPath.section == 1) {
// get the comment for this row
Comment *comment = [_comments objectAtIndex:indexPath.row];
// get the heights of the text areas
CGSize textSize = [comment.text sizeWithFont:font constrainedToSize:CGSizeMake(280 - 16, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
return textSize.height + 40;
}
return 60;
}
In the size constraint parameter, I subtract 16 units because the UITextView has a padding of roughly 8 units on both the left and right sides. This will give us a closer result to what we expected for the height of the text.
I also add some padding to the final height, of 40 units, because the row itself needs some padding around the UITextView.
There you go! Hope that helps.
UITextView scrolls even when all the text fits within its frame. It scrolls as if there are two new lines at the bottom of the text, but there aren't. So, its contentSize.height seems to be a couple lines larger than the text. How do I get rid of this? I.e., how do I tighten up the content size?
You can set up the contentSize for that UITextView so that it tightens to the text.
You can make use of NSString methods named sizeWithFont.... You can check full list here: http://developer.apple.com/library/ios/#documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html
I've noticed some issues working with some of them, but one that never fails me is:
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
I suppose you have a fixed width and want to find out the correct height. Considering a fixed 200px width, it would be something like:
NSString *myText = #"Some text...";
CGSize tightContentSize = [mytext sizeWithFont:[UIFont fontWithName:#"Helvetica" size:12] constrainedToSize:CGSizeMake(200, 10000000)].height;
[myTextView setContentSize:tightContentSize];
Take into consideration that your UITextView has an 8px padding in all directions, so if your UITextView frame is 200 width, you would actualy have a 184px width for text.
It's late but, for other people, try with:
self.textView.contentInset = UIEdgeInsetsZero;
That's work for me.