Unable to calculate height of text area in iOS - ios

I am using the ios library UIPlaceHolderTextView in my application: https://github.com/JohnnyZeng/UIPlaceHolderTextView which is linked to the following question:
Placeholder in UITextView
The library itself is working fine, however, I need to calculate the height of the area after the user has entered text, and unfortunately, I am always getting a value of 0.00000 despite the fact that the text area contains text. Why is this? Here is my relevant code:
//self.textView is a reference to a UIPlaceHolderTextView object, and text is its attribute
self.textView.text = #"Text that the user has entered, and can be of any length";
float height = MIN(175, [self.textView.attributedText boundingRectWithSize:CGSizeMake(self.textView.frame.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:NULL].size.height);
NSLog(#"textview height is: %f", self.textView.frame.origin.y);
NSLog(#"textview height is: %f", self.textView.frame.size.height);
The output in both lines are 0.00000. Can anyone see why this is happening? My guess is that the problem lies in the expression self.textView.attributedText, but not sure if I'm correct, and if so, what I should do instead.

you are assigning
`self.textView.text = #"Text that the user has entered, and can be of any length";`
and calculating heightfor self.textView.attributedText which is nil i guess please do appropriate changes. It should work.
To make is work you should assign value to self.textView.attributedText

Use a local textview of same width as real textview and set the same text with sizeToFit property.it will be returned in correct frame.
UITextView *tv = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, 50)];
//whatever alignment of real text view you have set
tv.textAlignment = NSTextAlignmentJustified;
tv.text= #"Text that the user has entered, and can be of any length";
[tv sizeToFit];
float height = tv.frame.size.height;

Related

How to shift subview of UITextView by size of one line when cursor goes to next line?

I have a textView and I added an image to this textView. When i write text and go to next line I want to shift this image down by size of one line.. Similar like in twitter app when you create a tweet with picture. In this code I can shift picture by line, but my problem is it shifts to late (only on second symbol of next line).. I tried to use different values in CGSizeMake but line was shifted too early or too late.. Any recommendations?
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
CGSize constrainedSize = CGSizeMake(self.textView.contentSize.width, self.textView.contentSize.height);
UIFont *fontText = [UIFont systemFontOfSize:17];
CGRect textRect = [textView.text boundingRectWithSize:constrainedSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:fontText}
context:nil];
size = textRect.size;
CGFloat height = ceilf(size.height);
CGFloat width = ceilf(size.width);
CGRect frame = CGRectMake(0.0f, height+50, 100.0f, 100);
_imageView.frame=frame;
return YES;
}
You are hardcoding your font size. Maybe the text field has a different font. Use textField.font instead.
Also, you should simplify your code and eliminate the unused variables, such as width.
Finally, you should set a breakpoint where you calculate the size and keep checking if it is correct. Based on that it should be easy to debug.
Also, please note that textField.text does not yet contain the text that is going to be added. Before checking the size, you would have to first construct the new resulting string yourself.
NSString *newText = [textField.text
stringByReplacingCharactersInRange:range withString:text];
I think you should add your Image as subview to superview of your textView.
In shouldChangeTextInRange: fit frame of textView to content of textView.
Then just use KVO for catch moments, when frame of textView was changed. So, now you can keep top border of image on bottom border of textview, even animated!
I wont write code instead you, but it sound very easily and interesting, right?

How to use NSLineBreakByCharWrapping with setNumberOfLines:1 on iOS?

For example, if the text for a UILabel is: "Questions that may already have your answer", I want it to print
"Questions that may alr". I don't want to clip the last character but cut the text at that point.
I cannot use a character limit as most fonts are not monospaced. I cannot use clipping as It may cut the text at another point or it may cut that last letter "r" from any where of it.
The behaviour I want is similar to NSLineBreakByCharWrapping while numberOfLines = 0.
So, I want it to drop(wrap) that non-fitting last character but I want it to drop/wrap to a hidden space = I don't want that second line.
How can this be possible?
To get required output you need to know width of the label, which can be known by following method:
CGSize size = [string sizeWithAttributes:
#{NSFontAttributeName:
[UIFont systemFontOfSize:17.0f]}]; // iOS 7 and later
CGSize size = [string sizeWithFont: [UIFont systemFontOfSize:17.0f]]; // prior to iOS 7
set the size of your label with the above calculated size.
set the numberOfLines property to 1;
set the lineBreakMode property to NSLineBreakByCharWrapping;
UILabel *yourLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, size.width, 50)];
placeLbl.numberOfLines = 1;
placeLbl.lineBreakMode = NSLineBreakByCharWrapping;
In swift 3.0
labelObject.numberOfLines = 0;
labelObject.lineBreakMode = NSLineBreakMode.byCharWrapping

Set UILabel Align top is not working in the cell

I have a problem to implement the text vertical alignment inside a table cell.
What I want to do is based on the length of the text I want to display a message top aligned in side one UILabel inside a cell.
For example if the message is only one line
The text should align top:
And if there are two rows then it should look like this:
At the beginning what I can see is like this
So I have searched the web and what I found is to
use the
[label1 sizeToFit];
But the problem with that is within the table view cell it is not always necessarily called especially when I switched to and from another tab view.
Then I tried to generate the label on the fly by code, but the problem is that let alone the complicated process of setting up the font format I want. I have to manage whether the label has been inserted or not then reuse it every time cellForRowAtIndexpath is called.
And more weirdly, once I select the row. The alignment is switched from the one you see in the first picture to the third one. It also happens when I switched to a different tab view and switch back to the view.
I was wondering if anybody has encountered such issue and have a solution to the problem.
Thank you for your reply in advance.
Edit:
#βḧäṙℊặṿῗ, what you said I have tried. It successfully align the label text if there is only one line. My situation is that, since I have multiple tab views. Once I switch back and forth between tabs view. The alignment just restored to centre-vertical alignment again. It also happens when I selected the row. Any idea?
Try this
// label will use the number of lines as per content
[myLabel setNumberOfLines:0]; // VERY IMP
[myLabel sizeToFit];
EDIT:
As you have one extra condition that maximumly display two lines then you need to set setNumberOfLines: to 2
[myLabel setNumberOfLines:2];
Create UILabel+Extras and add following methods to this class.
- (void)alignTop{
CGSize fontSize = [self.text sizeWithAttributes:#{NSFontAttributeName:self.font}];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGRect rect = [self.text boundingRectWithSize:CGSizeMake(finalWidth, finalHeight) options:NSStringDrawingTruncatesLastVisibleLine attributes:#{NSFontAttributeName:self.font} context:nil];
CGSize theStringSize = rect.size;
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i< newLinesToPad; i++)
self.text = [self.text stringByAppendingString:#" \n"];
}
Call this method like this..
[YOUR_LABEL alignTop];
Either You set no of Lines to be 0 like
[yourLabelObject setNumberOfLines:0];
[yourLabelObject sizeToFit];
Or
You can find the height of label at run time depending upon textString length.
Following method will return you the size(height & width) of label for length of text string.
here width is fixed and only height will change :
- (CGSize) calculateLabelHeightWith:(CGFloat)width text:(NSString*)textString andFont:(UIFont *)txtFont
{
CGSize maximumSize = CGSizeMake(width, 9999);
CGSize size = [textString sizeWithFont:txtFont
constrainedToSize:maximumSize
lineBreakMode:UILineBreakModeWordWrap];
return size;
}
Yo need to calculate frame of label each time when u r doing to set text and set frame of label
I hope this will helps you.
Might sound a bit silly but this is my approach: For any field that needs to be top aligned I fill the text up with multiple "\n"s. This causes the text to be automatically top aligned. Pretty much the same as Mehul's method above.
http://i.stack.imgur.com/8u5q4.png

UILabel LineBreakMethod

I tried to break a label according to the text that contains. The code is below:
mnhmeioLabel.numberOfLines=0;
mnhmeioLabel.lineBreakMode=NSLineBreakByWordWrapping;
[mnhmeioLabel sizeToFit];
Although it seems to work only sometimes. I added a snapshot of my problem and what i want.
The problem is in red box that breaks the line with a way that i cannot understand. The result that i want is in the yellow box.
I think there might be a space in the text that is coming from json.
Try this:
NSString * jsonAfterOmittingSpace=[jsonString stringByReplacingOccurrencesOfString:#" " withString:#""];
and then put this string on label
Seems like your label width is changing at runtime. use a Fixed width/height for your UILabel
first YouShould get label Height base on text
UILabel *mnhmeioLabel = [[UILabel alloc] initWithFrame:giveYourframe];
[mnhmeioLabel setText:heregiveYourText]
mnhmeioLabel.lineBreakMode=NSLineBreakByWordWrapping;
// get height base on label text and size
CGFloat height=[self getStringHeightforLabel:mnhmeioLabel];
//set fram after getting height
cell.mnhmeioLabel.frame=CGRectMake(cell.mnhmeioLabel.frame.origin.x,cell.mnhmeioLabel.frame.origin.y,cell.mnhmeioLabel.frame.size.height,height);
[cell.mnhmeioLabel sizeToFit];
// call this to get height
-(CGFloat)getStringHeightforLabel:(UILabel *)label
{
CGSize maximumLabelSize = CGSizeMake(label.frame.size.width,9999);
CGSize stringSize= [label.text sizeWithFont:label.font
constrainedToSize:maximumLabelSize
lineBreakMode:label.lineBreakMode];
return stringSize.height;
}

How to remove dots in UITextfield?

In iOS, I am using one text field the length of the text field id too long so it is showing dots at the end of the text field. I need to remove the dots. I have used lineBreakMode also.
See the code I'm using.
CGSize maximumSize = CGSizeMake(titleListTxtFld.frame.size.width, 1000); //here 1000 for maximum height u can increase this if u want
CGSize strSize = [titleListTxtFld.text sizeWithFont:titleListTxtFld.font constrainedToSize:maximumSize lineBreakMode:UILineBreakModeClip];
CGRect newframe = CGRectMake(0, 0, strSize.width, strSize.height);
[titleListTxtFld.text drawInRect:newframe
withFont:titleListTxtFld.font
lineBreakMode:UILineBreakModeClip
alignment:UITextAlignmentLeft];
Please anyone help me on this.
Another approach is (Remove dot and clip text to frame)-
your can remove dot from UITextField calling following code
[self.yourTextField becomeFirstResponder];
you can also hide default keyboard [if you use any custom keyboard] using following code
// Hide keyboard for Dial Pad, but show blinking cursor
UIView *dummyKeyboardView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
yourTextField.inputView = dummyKeyboardView;
[dummyKeyboardView release];
But I think IlNero's answer is better for you if you want to show all text (does not clip).

Resources