Multi-line UITableViewCell using UITableViewCellStyleValue2 style - iphone

I'm trying to figure out how to replicate the UITableViewCellStyleValue2 style so that the detail text can be multiple lines - as seen in the 'address' cells in the Contacts app. Like the Contacts app, some of the fields (like street name) are optional; so it would show say 3 lines instead of 4, if the street was not nil.
I'm I missing a trick, or do I have to create a custom cell in IB? How to ensure the text and detail text labels line-up with other UITableViewCellStyleValue2 cells?
Thanks for any tips.

Another round of searching found this:
http://the-lost-beauty.blogspot.com/2009/11/multi-line-uitableviewcell-using.html
Quickly tried it, and it works - just need to set the font size down a bit.

It sounds to me like you'll have to create a custom UITableCell. The only way to ensure the text lines up is to get the margin/text width values correct, which can be done via trial and error, or using a measuring tool such as xScope.

Create a custom cell for you table and place a UILabel and a UITextView inside it. Position the label & text view to match their x,y positions to the other cells you are using in that table. You insert "\n" in the textview's text wherever you want line breaks to occur. You resize the textview height depending on the number of lines in the textview using something like:
CGRect frame = yourTextView.frame;
frame.size.height = yourTextView.contentSize.height;
yourTextView.frame = frame;
return frame.size.height + 20.0; // Pad the cell's height as necessary for your applicaion

I also had the problem that the textLabel and the detailTextLabel had a different position. Solution: For the detailTextLabel use the same height like the textLabel (e.g. 13)

Related

UILabel not wrapping correctly after text change

I'm working via the IB and have a UILabel that's stretched almost to the end of the layout. I have it set with Lines=2, because the max amount of lines it should take is 2. However if it's only 1 line long, I would like it to have a vertical justification of top.
Label settings in IB:
Lines:2
Line breaks: Word wrap
In code, in the viewDidLoad method I set the text of the UILabel. However as part of the functionality at a point the text must change. This is my code:
[_main_lbl1 setText:[myUI MAIN_TITLE]]; //Always only 1 line
[_main_lblsub1 setText:[myUI SUB_TITLE]]; //May be 1 or 2 lines
[_main_lblsub1 sizeToFit]; //Causes vertical alignment (I believe)
Whenever I change the text and rerun sizeToFit, the text wrapping becomes totally messed up. Instead of reaching almost the end of the UILabel as set up in the IB, in some cases the text will wrap at little more than half the distance, in some cases it doesn't wrap at all.
Image of layout in IB:
Image of resulting label in simulator:
In the first label it seems to be working ok, the second label doesn't wrap at all.
Is there anything I have to do to keep the text wrapping when changing the UILabel text? Anything else I'm missing?
Note: Updated question to include more detail and pics.
Thanks
The issue is that you're using sizeToFit. Which stretches the label out to fit the text. If you need to change the size you can use:
CGSize maxSize = CGSizeMake(320, 9999); // 999 means it can be as tall as you like
CGSize textSize = [label.text sizeWithFont:label.font
constrainedToSize:maxSize];
label.size = textSize;
You shouldn't have to do anything special. It will automatically wrap the text to fit when you change it. Otherwise the text would run out of the text labels bounds (which is not what you want). Your problem is that sizeToFit permanently changes the frame of the label. It makes it as small as possible while still showing the text. You are having it resize its frame to the original text and then you are changing the text so it is no longer sized properly. You should reset the frame back to it's original, change the text, and finally call size to fit again.
In viewDidLoad:
self.originalFrame = self.mainLabelSub1.frame;
Then in viewWillAppear:
self.mainLabel1.frame = self.originalFrame;
self.mainLabel1.text = #"New Text";
Note:
A good way to see the borders of the text label to get an idea for the wrapping potential is to temporary set the background of the label to something like magentaColor that stands out.

UITableView with text that is both right-aligned and indented

I wanted to make a UITableView with text that is both right-aligned and indented as depicted in the image below:
Unfortunately, I can not do this by writing :-
cell.textLabel.textAlignment = UITextAlignmentRight;
cell.indentationLevel = 10; // or even -10
Can this be done using UITableView's properties? If not, the only way I could think of is using [myString drawInRect:withFont:]; but I would like to go through methods based on alignment and indentation before getting into that [I have already written code for that :-) ], so other work-arounds are welcome!
Additional info: The indentation varies with accelerometer values so I can not have hard-coded Label frame positions. I've uploaded sample code at github in which I've used only the alignment and indentation info so far, so continuing to use that would make this easier.
Subclass UITableViewCell and you can position the frame of the text label however you like. In the if statement where you dequeueReusableCellWithIdentifier: where a reusable cell doesn't exist, just modify the frame and then set the label to use the adjusted frame with setFrame. The autoresizing mask should remain the same.
You could always create your own custom cells and place a UITextLabel in the cell, and make the UITextLabel's alignment right aligned.
Also set the autoresizing mask of the UITextLabel to the right so the indentation distance stays the same no matter the orientation.

iphone code for auto uiLabel & uiTableViewCell resizing when font changed?

Can someone summarise the key pieces of objective-c code that would assist in solving this.
Objective - Autoresize a UITableView after a user changes the font size. Therefore if the user increases or descreases font both the (a) uiLabel heights should change to ensure they nicely include text, and (b) uiTableViewCell heights should also adjust.
Assumption is that:
UITableView has been extended via
creation of a custom cell view -
i.e. create a new view in a NIB that
forms for the content view of the
UITableView cells
each custom
cell has four UILabel's which form a
2 x 2 patter of UILabels - i.e. two
on top line and two on bottom line
so as the user increases the font
the horizontal spacing of the
UILabels would remain the same,
however the label heights would
change
So I assume the challenge / questions I have would include (and hopefully be answered by some sample code that someone can post)
Is it OK that the starting point here is an already laid out custom UITableViewCell in InterfaceBuilder? (or does the solution require it is constructed totally programmatically)?
How to calculate the heights the label's should be? Is this just with the NSString method "sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:", and do I need to add addition for margins etc?
How programmatically to increase the height of the labels dynamically - in which method do you do this & how to change the height itself
How to ensure that when UILabel at the top is expanded & grows, that it automatically pushes down the UILabel on the 2nd row? Does this happen by default or is there a specific property/setting you have to you to ensure this hapens.
How to then automatically increase the height of the TableViewcell, after the above has occurred. Which method to do this in, and how programmatically to perform the increase & redraw.
Hope this makes sense.
thanks
You can base on the XIB file as a default layout, then adjust the position/size later during runtime.
Yes use that method to calculate the required height. You need to add margins between labels yourself.
Change the label's frame.
You need to calculate the x,y of the 2nd row's label base on the x,y,height from the 1st row's label + margin.
hook with the following method and return the new height:
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
To get the UILabel's height to match your target font, you use the sizeWithFont function of NSString.
NSString *myText = #"Go Hokies";
UIFont *myFont = [UIFont boldSystemFontOfSize:15];
CGFloat lineHeight = [myText sizeWithFont:myFont].height;
The problem you may run into is if the text doesn't fit horizontally in the bounds you've defined. If you want the font to downsize accordingly, turn on the adjustment flag and set a min like this.
myUILabel.minimumFontSize = 10;
myUILabel.adjustsFontSizeToFitWidth = YES;

How to configure iOs UITextViews and UILabels so that their height is determined by their content

I am basically trying to find the correct way to design a UITableViewCell that has two UITextViews and three UILabels inside it. The two UITextViews have dynamic content and their size cannot be determined until runtime.
I have tried various methods of recalculating the height of my UITextViews based on the content that is loaded in them at runtime, and though very laborious and inane, I have gotten that to work, but they then bleed over the UILabels positioned in the xib below them.
Do I really have to recalculate the y coordinates of every UILabel after calculating the new size of the UITextViews? Is there a way to simply have the elements in the xib 'push' the elements below them down based on their new size?
What is the correct approach to configuring a UITableViewCell with multiple dynamic text views so that my entire application is not comprised of code to calculate heights and coordinates?
Or is the answer that I should not be putting more than one dynamic UITextView in the same UITableViewCell ?
I have used something like this for a cell to calculate its height in
tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
function
CGSize labelSize = [self.comments sizeWithFont:[UIFont fontWithName:#"Verdana" size:17.0]
constrainedToSize:CGSizeMake(280.0f, MAXFLOAT)
lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 20;
+20 is for padding.
and also if you are having every cell like the one you mention above, than you can create a class of UITableViewCell with following UIView elements inside it.
iOS doesn't seem to have any sort of flow layout engine -- at least none that I can think of.
If, however, your labels are located at the bottom of your UITableViewCell, you might be able to get away with setting the UILabel's autoresizingMask mask property to UIViewAutoresizingFlexibleBottomMargin so that the UILabels will anchor itself at the bottom. This is assuming that you already adjusted the size of the UITableViewCell to fit the entire controls. Otherwise, I think the best way to handle this is to recalculate the y coordinates of the labels.
I found it useful to add this sort of behavior as a category on UIView so a view can resize one of its subviews to fit some arbitrary text, and optionally resize the parent view to fit the newly enlarged subview as needed.
http://blog.carbonfive.com/2009/07/10/resizing-uilabel-to-fit-text/

UITableViewCell - how to make right UILabel truncate instead of left one?

I have created a UITableViewCell using UITableViewCellStyleValue1, which the Apple docs define as:
A style for a cell with a label on the left side of the cell with left-aligned and black text; on the right side is a label that has smaller blue text and is right-aligned. The Settings application uses cells in this style.
I am trying to set the cell text to display some short text on the left, and some long text on the right, e.g.
URL http://www.mylongurl.com/subdirectory/etc
My problem is that the left UILabel gets truncated instead of the right one so it displays as:
U... http://www.mylongurl.com/subdirectory/etc
If I make the URL even longer then BOTH the labels get truncated, e.g.
U... http://www.mylongurl.com...subdirectory/etc
Is there any way to make the right UILabel truncate instead of the left one without using a custom UITableViewCell? I know how to create a custom UITableViewCell, but it seems like overkill?
I can set the UILineBreakMode to change where the text truncates within the UILabel, but I can't see a way to make the detailTextLabel adjust its width to let the textLabel display itself.
[[lCell textLabel] setText:#"URL"];
[[lCell detailTextLabel] setText:#"http://www.mylongurl.com/subdirectory/etc"];
[[lCell detailTextLabel] setLineBreakMode:UILineBreakModeMiddleTruncation];
You have a couple of options.
Probably the closest in spirit to what you seem to be asking for is to muck around with the label frames in your UITableViewDelegate's tableView:willDisplayCell:forRowAtIndexPath:. (Doing cell layout modifications in your UITableViewDataSource's tableView:cellForRowAtIndexPath: won't fly, since UITableViewCells do all their own internal layout work after tableView:cellForRowAtIndexPath:.) You can use NSString's -sizeWithFont: to help figure out the layout requirements for your textLabel.
You can also take different approaches, as you mentioned, such as subclassing UITableViewCell or setting cell.textLabel.adjustsFontSizeToFitWidth = YES.
The best solution would be to create a subclass of UITableView cell and set your customizations to the labels like you have here in init. You will probably want to override layoutSubviews and resize the labels if you want the left one to be wider.
- (void)layoutSubviews {
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0.0, 0.0, 100.0, self.frame.size.height);
self.detailTextLabel.frame = CGRectMake(0.0, 0.0, 220.0, self.frame.size.height);
}
Obviously those are arbitrary values. You will want to play with different sizes to meet your needs.