Adjusting row height correctly - iphone

Showing dynamic data in table cell make problem for me. I am using
[titleString sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(285,9999) lineBreakMode:UILineBreakModeWordWrap];
function for calculating the size now according to size i need to adjust row sizes. but it is inconsistent, Some time it give size(242,18) and (40,18) (showing width,height). when it gives more width for same height the it breaks in two line text and inconsistency begins. if i take less height then it overflow the text and if less in height then some time left a huge white space.
please help me and suggest some proper way for doing this.

you code seem me correct , there is only one place for modification left in your code that would be use CGFLOAT_MAX instead of 9999.
And Also check the lineBreakMode property, Assign numberOfLines With zero.
label.numberOfLines = 0;
label.lineBreakMode = UILineBreakModeWordWrap;

There is delegate method as follows
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == theRowWhereUwantToIncreaseTheSize)
{
return 105.0f;;
}
}

Related

Remove spacing between UITableViewCells

I have UITableViewCells in the same section which have gaps between them. I coloured each cell's contentView background and did an NSLog to show that it's the same height as the cells.
Still, there's a gap between them. They're definitely in the same section as each other. Any ideas as to what could be causing the gap?
I'm not sure if you have used this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
And Checked that the Cell really is 78(just for arguments sake) in IB.
And then use:
tableView.sectionHeaderHeight = 0.0;
And set the style of the tableView:
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
And the last solution I've bumped into over the years is that sometimes you need to extend your background image with a pixel for some reason. I don't think this is a good solution at all, cause it doesn't really address the real problem, but rather puts a crappy bandaid on it.
cellFrameBackground.size.height += 1;
have you tried setting seperator style to none?
tableview.separatorType = UITableViewCellSeparatorStyleNone
If you are talking about a 1 pixel gap, that is the cell separator. You can remove this by setting a property on the table view:
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
If you wanted to change the color of that separator use the separatorColor property.
If you are talking about a gap bigger than 1 pixel, can you post a screenshot and your cell code?
To add to the set of great answers, sometimes you just need to extend the background height as mentioned by Leeloo:
cellFrameBackground.size.height += 1;
Then, make your cell clip to bounds:
cell.clipsToBounds = YES;
And, voila.

UIFont size unset prior to UITableCell display - how to cleanly calculculate height

Minor quest - looking for a clean way to dynamically set the size of tables in a resonably generic way (snippets below are from http://pastebin.com/E2pUFRg4).
Now I thought something like
-(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(self.view.bounds.size.width-24.f, CGFLOAT_MAX);
UITableViewCell * cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGSize size = [text sizeWithFont:cell.textLabel.font
constrainedToSize:constraint
lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height + 12.f, tableView.rowHeight);
return height;
}
would nicely cut it. But unfortunately on the first call to tableView:heightForRowAtIndexPath: the size of the font on the textlabel is set to 0 (the font itself is otherwise setup). It only gets popoulated to something sensible after the first draw.
So I find myself having to change this to something like:
....
UIFont * font = cell.textLabel.font;
if (font.pointSize == 0)
font = [UIFont systemFontOfSize:20];
CGSize size = [text sizeWithFont:font
constrainedToSize:constraint
lineBreakMode:UILineBreakModeWordWrap];
.....
which does the trick. But now we suddenly have a hardcoded font size assumption of 20. Which sort of sucks.
So my questions now are
Any way to prevent this ? I.e. hardcoding it this much ?
I also guesstimate the X and Y borders/inset at 2x6 vertical and 2x12 horizontal.
is there any way to learn this dynamically or from a constant (as to make it as close to the proper defaults on an iPhone and iPad-UIPopover view) ?
And finally:
Suggestions for a cleaner way to do this - which also allows for the detailLabel or similar extra fields to be taken into account.
Complete sample at http://pastebin.com/E2pUFRg4.
Thanks,
Dw.
I think you need to more or less "hardcode" your font size anyway. If you get it from interface builder, or from a central constants file - or even in code - it is always somehow hardcoded.
If you need to distinguish between device types (iPhone, iPad) etc. you can still use different values according to UI requirements.
I usually set up a central configuration file for values like this. There you could also "hardcode" your standard margin values, as well as the font sizes of other cell labels. It is common practice to calculate as many values dynamically as possible to reduce the number of constants, but to still resort to constants to "anchor" these values.

Can I have cells with different hight in an UITableView?

I need to present some information in a table view where some information is pretty flat, and other is pretty big. i.e. one information is just a line of text really, while the other is three lines of text.
From what I know, UITableView asks for the hight of all cells. So is there any way to have cells with distinct heights?
Yes, see:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Example implementation:
NSString *string...;
CGFloat CellWidth...;
CGSize size = [string sizeWithFont:[UIFont systemFontOfSize:14.0]
constrainedToSize:CGSizeMake(textWidth, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = size.height;
if (height + 13.0) < 44.0) {
return 44.0;
}
return height + 13.0;
I agree with paull, but you could also subclass if you wanted something extra than just resizing the height. Just think about what else you may need. Good luck, cocoa can be a real pain sometimes.

sizeWithFont doesn't give correct height for UITextView if there is a long string in the text being wrapped

Is there a way to get the correct size of an NSString using:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
that doesnt get thrown off by 2 or 3 hundred character strings. At the moment if I try to use this method on these long strings it incorrectly calculates them and I end up with lots of whitespace at the bottom of the UITextView.
I've tried using UILineBreakModeWordWrap and UILineBreakModeCharacterWrap.
the resizing is being done in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat result = 44.0f;
NSString* text = nil;
CGFloat width = 0;
CGFloat tableViewWidth;
CGRect bounds = [UIScreen mainScreen].bounds;
tableViewWidth = bounds.size.width;
width = tableViewWidth - 150;
text = stringWithLongWords;
if (text) {
CGSize textSize = { width, 20000.0f };
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:10.0f] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 50.0f;
result = MAX(size.height, 44.0f+30.0f);
}
return result;
}
UITextView is not exactly like a UILabel wrapped in a UIScrollView. It has line spacing different from the font size and margins that sizeWithFont:constrainedToSize:linkBreakMode: doesn't account for.
Knowing your font size you might be able to calculate the # of lines and take line spacing into account. You can guess at the margins and try to trick sizeWithFont: to give a more useful answer.
The popular solutions seem to be:
just use a UILabel if you don't need any UITextView functionality
if you need hyperlinks, overlay UIButtons that look like hyperlinks over a UILabel
use an off-screen UITextView and its sizeToFit method to get a real answer
I had no luck w/ the 3rd option but it sounds like it should work, so perhaps I did something wrong.
I'm going to try using a UILabel and overlaying buttons for hyperlinks. We'll see how that turns out.
If that fails, there is always the option taken by Loren Brichter (of Tweetie fame): draw everything into a UIView yourself using CoreGraphics.
Good luck!
Check out this post How do I size a UITextView to its content?
It looks like textView.contentSize.height should work (with the caveat that the the correct contentSize is only available after the UITextView has been added to the view with addSubview)
You said that you have a UITableView with differing heights. Have you set the reuse identifier to the same thing for all of the cells? It could be that older cells with their height already set are being reused. If this is the problem, you should resize the cell again when it's being reused.
The best solution I have found so far is to have a separate hidden UITextView with the same font settings, and set its text. After that its contetSize should be accurate.
The width you are using is the width for your UITextView... but you aren't concerned with that width, you are concerned with the width of the actual text area nested inside the text view.
UITextViews, by default, have padding around their borders to produce a space in-between the typed text and the edge of the UITextView a few pixels wide (and long for the top)... To get the correct size you shouldn't use
textView.frame.size.width
but rather,
textView.frame.size.width-(textView.contentInset.left+textView.contentInset.right+textView.textContainerInset.left+textView.textContainerInset.right+textView.textContainer.lineFragmentPadding/*left*/+textView.textContainer.lineFragmentPadding/*right*/)
^Which takes the width of the UITextView and subtracts out all the padding so you are left with the width of just the type-able text area.
Same goes for height except for lineFragmentPadding doesn't have a bottom so you only subtract it out once instead of twice.
The final code is something like this:
CGSize textViewContentSize = CGSizeMake(theTextView.frame.size.width-(theTextView.contentInset.left+theTextView.contentInset.right+theTextView.textContainerInset.left+theTextView.textContainerInset.right+theTextView.textContainer.lineFragmentPadding/*left*/+theTextView.textContainer.lineFragmentPadding/*right*/), theTextView.frame.size.height-(theTextView.contentInset.top+theTextView.contentInset.bottom+theTextView.textContainerInset.top+theTextView.textContainerInset.bottom+theTextView.textContainer.lineFragmentPadding/*top*//*+theTextView.textContainer.lineFragmentPadding*//*there is no bottom padding*/));
CGSize calculatedSize = [theTextView.text sizeWithFont:theTextView.font
constrainedToSize:textViewContentSize
lineBreakMode:NSLineBreakByWordWrapping];
CGSize adjustedSize = CGSizeMake(ceilf(calculatedSize.width), ceilf(calculatedSize.height));
Inspired by #MrNickBarker's answer, here's my solution:
CGFloat width = 280.0f;
UITextView *t = [[UITextView alloc] init];
[t setFont:[UIFont systemFontOfSize:17]];
[label setText:#"some short or long text, works both"];
CGRect frame = CGRectMake(0, 0, width, 0);
[t setFrame:frame];
// Here's the trick: after applying the 0-frame, the content size is calculated and can be used in a second invocation
frame = CGRectMake(0, 0, width, t.contentSize.height);
[t setFrame:frame];
The only issue remaining for me is that this doesn't work with modified insets.
Still can't believe such twists are required, but since -[NSString sizeWithFont:forWidth:lineBreakMode:] does not respect insets, paddings, margins, line spacings and the like, it seems this is the only working solution at the moment (i.e. iOS 6).

How can I make a multiline label in a UITableView?

How can we make the text in the label of a table view go to the next line?
//This allows for multiple lines
cell.textLabel.numberOfLines = 0;
//This makes your label wrap words as they reach the end of a line
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
Also, if you want your label to have more room for such multiple lines, you probably should allow for table rows with greater height. You can do this either by overriding
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
and returning your custom height for each row there, or by specifying your table's rowHeight property, giving the common height of each row.
Try adding "\n" in the label, eg:
#"Hello,\nworld!"
you can try to use cell with subtitle( initWithStyle:UITableViewCellStyleSubtitle ). if it is not exactly what you want, you can customize your cell by adding UITextView(or, maybe, several UILabels) to it as a subView(s).