I have a segment of code that gets executed everytime a backend database change occurs. Essentially I have a label inside of a parent view. The label gets updated by one of many status messages each one on a different line ended by a new line (\n). Each status message needs to be on one line only and not go over.
The problem I am having is that everything works fine when the View first reloads. However when I am on the screen and a change occurs in background, once in a while a status message displays on multiple lines. While sizeToFit does a great job of making the label as high as the parent containing view, it does so poorly in terms of width. That is it will break up text on multiple lines as opposed to looking at the line breaks only.
What can I do?
self.messageLabel.text = message; //lets get the status message.
[self.messageLabel sizeToFit];
[self.messageLabel setNeedsDisplay];
CGRect frame = [self.messageView frame];
frame.size.height = self.messageLabel.bounds.size.height;
self.messageView.frame = frame;
self.messageLabel.center = CGPointMake(CGRectGetMidX(self.messageView.bounds), CGRectGetMidY(self.messageView.bounds)-(self.messageView.cornerRadius/4));
self.messageLabel.backgroundColor = [UIColor orangeColor];
[self.messageView setNeedsDisplay];
In order to determine the size that your label will need to be, you need to look into the NSString size methods. There's a number of them that can tell you the size a string will be given a font, and various constraints.
For example [#"string" sizeWithFont: forWidth: lineBreakMode:]; will return a CGSize that you can then use to size your label appropriately.
As an aside, I find the UILabel does not handle strings with multiple lines well. You may be better off writing your own subview of UIView that can handle multiple lines of text, each with its own label.
It seems to happen each time the frame is resized after the initial operation. Presumably the frame's current size is used when deciding the new size in -sizeToFit.
The workaround I'm using is to set the view's frame to a pre-defined size before each call to sizeToFit, e.g:
myLabel.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.width.height);
[myLabel sizeToFit];
Related
I ran into an issue where clipping of subviews is not working consistently (or potentially, the UIView resize isn't working). Here's the scenario:
I have a UIView (section above the line). The actual size is larger to accommodate search bar. I basically resize it on viewDidLoad.
When clicking on the text field, UIView expands and show a search bar
After search, I collapse the UIView, but found that the UIView is not collapsed in certain case (see first image). If I were to not hide the search bar, it will remain also.
Is there any reason why this issue occurs? I'm still trying to debug and see if there is anything that could have caused this issue (as something may reset to original size). It definitely does seem like everything is resized correctly since even the result table is moved correctly also. Something else must have triggered it after the expected resize. Any pointer is appreciated. I've only done iOS development for 5 days so I'm still not aware of a lot of things.
- (void)showAddressField
{
CGRect headerFrame = self.searchHeaderView.frame;
headerFrame.size.height = headerHeight + adjustmentSize;
self.searchHeaderView.frame = headerFrame;
CGRect tableFrame = resultTableView.frame;
tableFrame.size.height = tableHeight - adjustmentSize;
tableFrame.origin.y = headerFrame.size.height + statusBarHeight;
resultTableView.frame = tableFrame;
[self renderHeaderBorder:headerFrame.size.height - 1];
}
- (void)hideAddressField
{
CGRect headerFrame = self.searchHeaderView.frame;
headerFrame.size.height = headerHeight;
self.searchHeaderView.frame = headerFrame;
CGRect tableFrame = resultTableView.frame;
tableFrame.size.height = tableHeight;
tableFrame.origin.y = headerHeight + statusBarHeight;
resultTableView.frame = tableFrame;
[self renderHeaderBorder:headerHeight - 1];
}
EDITED
SearchHeaderView is just a UIView that is a subview of the main view. It's not a table header. I found that if I put a search bar in the table header, it behaves very unpredictably so I have a UIView containing the search portion and have a UITableView right below it.
Sorry, since I only have just over a week to get a rather massive app out from scratch, I didn't have time to wait. I already changed my approach a little bit, but I will still award the points even after the bounty has expired. I'm trying to understand everything to do with layout since that's pretty much the only thing that I can't quite figure out with iOS app development.
If the search bar is in the table view header, try reassigning the header view to the table view:
[tableView setTableHeaderView:self.searchHeaderView];
If it is a section header, be sure to update the value for the delegate's
– tableView:heightForHeaderInSection:
– tableView:viewForHeaderInSection:
Otherwise, please post more code on how the searchHeaderView is initialized and added to the table.
Hope this helps!
Firstly, frames are already relative to the enclosing window. You should not be taking into account the height of the status bar (assuming that refers to the 20px area at the top of the screen).
I have found in the past that you may need to implement "layoutSubviews" in your view controller and compute the frames of the views there. It depends on your resizing mask / if you auto-layout enabled.
As the others have stated, more code would be helpful... or at least the relevant portions of the nib/xib.
I am working on a simple storyboard prototype. My TableViewController uses Dynamic Prototype as Content.
I have a cell with 4 label of which two will be set in code (the label text). The height of the cell will be calculated in code too. The Line Breaks are set to Word Wrap and everything's working fine with the default values (System 17.0):
see here:
..but if I change the Font Size of the "Fantasy Street..." label it will not break any more instead it just will be cut off!
see here: with System Font 16
Lines are set to 0
Word Wrap is still active
.. I also tried to do it manually in code but no change.
Does anyone have an explanation for that?
****edited:** when I add
myLabel.frame = CGRectMake(t.origin.x, t.origin.y, t.size.width, t.size.height *2);
to the cellForRowAtIndexPath I still see the cut off label. But if I then scroll the table view so the label is outside the viewable area shortly it will be displayed with the complete text when it is visible again.
By the way, I am working with viewTags, so I don't have a dedicated Cell Class e.g. UILabel *myLabel = (UILabel *)[cell viewWithTag:2];
You should check UILabel width; the width should be less than that of the value. Then like this:
(void) viewWillLayoutSubviews {
_landPhoneTips.preferredMaxLayoutWidth = _landPhoneTips.bounds.size.width;
}
I spent hours dealing with this identical problem before finally sorting it out last evening. After changing the font size, you must select the UILabel within the storyboard and select Edit > Size to Fit Content, even if you had already previously done so! In doing so you apparently reset some setting that gets messed up when changing the font size. Once done, the UILabel will wrap as it did previously.
I have a custom table cell with a UILabel in. What I want can be done with two ways.
1- Find the height of the Label that contains long text and set the rowHeight to make the whole text visible.
2- Make the UILabel scrollable so the user can move the text up/down with his hand to read the whole string.
Can you please advice me on which one to do an how to do it?
If your text is static and won't change dynamically, you should use the first option. You can cache the result so whenever you refresh the table, you won't have to recalculate the text. You can use sizeWithFont:constrainedToSize:lineBreakMode to calculate the actual text size.
For the row height: you should use tableView:heightForRowAtIndexPath: and not rowHeight, since rowHeight will change the height for ALL rows - not only a single cell.
A far as a scrollable text view inside a table: in my opinion - it looks like a cheap solution in an app and makes it a bit amateur.
I recommend not using the first option in most cases as depending on the length of the string it could make your table cells huge.
As for the second option: You should be able to add a UIScrollView as a subview into the table view cells. The Scroll View can contain the fully sized text labels and let you scroll through them within a fixed size cell.
Do we have any example on how to do it? Im new to iphone, sorry for
bugging. – Panos 9 mins ago
UIScrollView *scroller = [[UIScrollView alloc]initWithFrame:cell.frame];
scroller.contentSize = CGSizeMake(280, 100);
UILabel *test = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
test.text = #"This would be your label.";
[scroller addSubview:test];
[cell addSubview:scroller];
This will make a UIScrollView and a label in the tablecell 'cell'. This will work, but I do not think this is the best solution, since it's gonna be a scrollview inside a tableview which already provides scrolling. My advice is to adjust the rowheigth.
I am quite new to iphone development. I have a situation here. I have some labels which can be dragged across the screen.
What I want is when any of these labels are dragged to some textfield and released over a textfiels UIlabel test is assigned to that text field.
The crux in this is I have to check for a condition when UILabel is inside UITextfield.
Can you help me to fabricate this condition.
Thanx in advance
This might not be the best way, but it should work:
CGRect textfieldFrame = textfield.frame;
CGRect labelFrame = label.frame;
if (!CGRectIsNull(CGRectIntersection(textfieldFrame, labelFrame))) {
// the two objects' frames are overlapping
}
This only works I believe if the two objects are attached to the same view, but it should get you started.
Does anyone know how to create a text field that has a UIImage background and does word-wrapping?
It appears that word-wrapping is not available on UITextField, while a background image is not available for UITextView! Also, it should change the size of the control or at least alert that the number of lines changed so that a delegate could change its size..
An example of such control is the input field for messages in the SMS application.
Edit: the code should also get the text field to always show the text being edited. Apparently, when UITextView changes size while editing it somehow loses focus on the current text.
Thanks ahead!
Aviad.
Word-wrapping is not available on UITextField because UITextField only supports single-line text.
Use a UITextView. Make textView.backgroundColor = [UIColor clearColor]. Add the UIImage first, then the UITextView on top of it. Make sure the sizes are correct, and you should be fine.
As for changing the size of the UITextView, in your UITextViewDelegate, do something like this:
- (void)textViewDidChange:(UITextView *)textView
{
NSString *s = textView.text;
CGSize testSize = CGSizeMake(textView.frame.size.width, NSIntegerMax);
CGSize neededSize = [s sizeWithFont: textView.font constrainedToSize: testSize lineBreakMode: UILineBreakModeWordWrap]; // or UILineBreakModeCharacterWrap?
if (neededSize.height > testSize.height)
{
// grow textView
textView.frame = CGRectMake(textView.frame.origin.x, textView.frame.origin.y, neededSize.width, neededSize.height);
// then adjust the image size -- something like this
imageView.frame = textView.frame
}
}
Eventually I wrote my own code, which worked to some degree with a lot of workarounds (changing the focus for example, resizing when removing all the text again, etc). If anyone's interested, I'll post the code.
In other news, just today I saw in a different question around here something called IFVerticallyExpandingTextField. The name was promising, the code is here, and I'll give it a look. Anyone with a similar problem, you might want to see this too.
My mistake, I didn't read it carefully enough: IFVerticallyExpandingTextField is for the Mac, not the iPhone.