How do I prevent text from being cut off like in UITextView? - ios

I have a UILabel and a UITextView both with the same text (the string "SnellRoundhand", in Snell Roundhand Bold font, point size 21). The text in the UITextView appears correctly, but the UILabel has its text cut off on the left and right sides. How do I get the text in the label to appear properly?
Some notes:
Expanding the frame of the label won't work because it might solve the cutoff issue on the right side of the text but not on the left side.
I can't take the cheap way out and center the text; the text must stay at whatever alignment it is in right now.
The reason I can't just change everything to UITextViews is because my app does some processing in the background and it crashes whenever it instantiates a UITextView. I'm hoping I can get around the issue by using UILabel instead to render the text.

In iOS 6, a very nice new feature of UILabel is that it supports attributed strings. Attributed strings can include paragraph margins. So you can add margins to your string, thus ensuring that there will be some extra space between the edges of the label and the drawing of the string.
This section of my book has sample code that adds margins to a string drawn in a UILabel:
http://www.apeth.com/iOSBook/ch23.html#_attributed_strings
If you want to run on a system earlier than iOS 6, you can subclass UILabel to force the text to be drawn inset from the edges of the label, as shown in this code (also from my book):
- (void)drawTextInRect:(CGRect)rect {
[super drawTextInRect:CGRectInset(rect, 5.0, 5.0)];
}

I don't have a good answer, but I can suggest a kludge that sorta does what you want done and might give you some useful ideas. The problem sure seems to suggest a fundamental problem with Label and TextView handling for funky fonts.
The concept is simple enough:
Size the TextField with left (or right) justification to just fit the contents.
Slightly enlarge the text field width.
Change the justification to center.
This will result in a field just wide enough to display the text without clipping (if you enlarge it the right amount). I know you said you couldn't change the text alignment, but doing it this way only moves the text a point or two and it ends up where it needs to be to display the full text. The field ends up the size, and the text in the position it ought to be. For instance:
self.textField.textAlignment = NSTextAlignmentLeft;
[self.textField sizeToFit];
CGRect frame = self.textField.frame;
frame.size.width += 4;
self.textField.frame = frame;
self.textField.textAlignment = NSTextAlignmentCenter;
This works. If it isn't useful to you directly I hope it gives you some ideas.
Something I tried that wasn't helpful was subclassing UITextField and overriding the textRectForBounds: to enlarge the area used to draw the text. I could move the text starting position slightly to the right, but it still clipped the left edge. Turning off the clipsSubviews property didn't help. Seems like Apple's problem here.

On iOS 6 the UITextView has a margin on each side, you can adjust the content inset to prevent the text from using those margins.
[textView setContentInset:UIEdgeInsetsMake(-8, -8, -8, -8)];

Related

UILabel alignment right issue

I have a problem with UILabel in Swift. Problem happens when text is changed often (like a time readout) in the label.
With alignment left everything works perfect. But I need alignment right.
And in this mode text jumps left and right when changed. This jump is about 1 pixel.
May be someone know how to solve this problem?
Based on the code in your comment:
label.font = label.font.withSize(12)
You are using the standard iOS system font, which is not monospaced, and therefore will cause spacing issues when the text changes. If you use a monospaced font (Courier, Menlo, etc), this issue will go away.
Alternatively, you could handle the drawing of the text yourself or adjust the font's kerning.

Calculation Frame of a UILabel Subclass

The bottom line is that I'm trying to reproduce the UI that iMessage has.
For the Label:
The special padding of that type of text made me create a custom UILabel. Here's the code under drawTextInRect:
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, UIEdgeInsetsMake(0, 15.0, 5.0, 15.0))];
No mystery for now.
The problem comes when my cell (that contain that label has to calculate height).
The Label gets a rounding effect on the label like so:
cell.message.layer.cornerRadius = 18;
[cell.message sizeToFit];
Apparently I can't get the proper height and width of that label. I'm using sizeToFit and then I mesure the possible sizes with "sizeWithFont:" (deprecated in iOS 7) and "boundingRectWithSize:".
The only way the text can show properly is adding manually an undetermined amount of size to height and width once the calculations are made.
The best I can get then is a screen that may look good but still has some problems and not draws properly the texts.
The link has a screen of some of the screens not showing properly.
The only answer I've been able to see looking at code from other people is that they at some point make their own calculations based on letter size.
Anyone with this problem check : https://github.com/jessesquires/MessagesTableViewController
It was the only source I could find, at the end for some cases the boundingRectWithSize is not good enough.

Remove UITextView extra border

I've made a UITextView yet there's some unwanted spacing:
(I'm drawing the white box separately). I'm fairly certain I got the coordinates right since if I scroll it gets cut off at the right places:
How can I make the text be drawn further to the left, and also to have the top-most position be further on the top? That is, I'd like it to look like this:
I've tried [[textView layer] setBorderWidth:0.0f], but to no avail - it already doesn't have a border. This is what it looks like if I set the border width to 2 and to the color red:
I'm curious where the extra spacing is coming from and how to control it.
Have you tried experimenting with textContainerInset?
According to the docs at developer.apple.com, "This property provides text margins for text laid out in the text view." This is new in iOS 7.
It seems that the following does the trick:
UITextView *textView = ...;
[textView setContentInset:UIEdgeInsetsMake(-10, -8, 0, 0)];
The result is exactly as I wanted it to be. This isn't too satisfying as it uses magic numbers, so if anyone has a better answer, feel free to comment or answer.

UILabel with NSAttributedString is clipping content

I've got a UILabel set up with auto layout in such a way that its height is based on its intrinsic content size, such that it gets taller when there are more lines in it. I need it to be centered alongside other elements in the same view. With everything default, it works just fine.
However, I'm using a custom font that has a bit too much space in it. I've set up an NSMutableParagraphStyle, like so:
NSMutableParagraphStyle *headlineParagraphStyle = [NSMutableParagraphStyle new];
headlineParagraphStyle.lineSpacing = 0.0f;
headlineParagraphStyle.maximumLineHeight = 20.0f;
headlineParagraphStyle.hyphenationFactor = 0.0f;
headlineParagraphStyle.alignment = NSTextAlignmentLeft;
I'm then creating and setting an NSAttributedString as the UILabel's -attributedText:
NSString *uppercaseHeadline = self.currentStory.headline.uppercaseString;
NSAttributedString *attributedHeadline = [[NSAttributedString alloc] initWithString:uppercaseHeadline attributes:#{NSParagraphStyleAttributeName: headlineParagraphStyle}];
self.headlineLabel.attributedText = attributedHeadline;
The result is that the text looks okay, but it's shoved up above the top of the UILabel and clipped off at the top, while there's still extra space at the bottom of the label:
This also throws off the centering of other items against the text in this label, since you can see that the space between the two lines does not line up with the center of the label's frame.
How can I tell UILabel to recenter this text, so that the top doesn't clip and there isn't any space at the bottom?
I've realized I never came back and answered this question after iOS 7 was released and the NDA on that platform lifted. As of iOS SDK 7.0, it is possible to use the NSAttributedString attribute NSBaselineOffsetAttributeName, which did exactly what I needed to do.
It was available but "no longer supported" in iOS 6. However, when building with the iOS 7 SDK, it appeared to do the right thing.
Edit: In case it's unclear, I don't recommend doing this. If Apple says it's no longer supported, it's probably not a good idea to rely on it. It worked for me, but it's definitely not a long-term solution.
I just had a wild ride with this. For whatever reason, using lineHeightMultiple, maximumLineHeight, and/or minimumLineHeight blows the offset like this.
However, using lineSpacing (which is not an absolute value but a relative value) will change the spacing between lines without messing up the offset.
In iOS 10, my solution was to only set maximumLineHeight and to NOT set minimumLineHeight (otherwise, the top of the label gets clipped). Changing lineSpacing or lineHeightMultiple did not help.
I feel it's important to link to the 'bizarre interview': http://i.imgur.com/pFeqPHd.gif.
You may need to edit the font's ascender property, see here: UIButton custom font vertical alignment
in my case numberOfLines = 0 was needed
otherwise, counterintuitively, line after the newline were clipped

how to get uitextview text in particular area

i need to get text from uitextview. The text i need is in particular area after scrolling the textview, not all the text in uitextview.
i'll describe what i need in some images.
first, i have this textview
then, i want to get some text, like in this image :
but i dont know how to do that, can somebody help me ?
thank you
NSRange range = NSMakeRange(desired_position, 0);
[myTextview setSelectedRange:range];
Interesting and unusual question.
[Rewrite for UITextView, originally written for UITextField]
A UITextView is basically a text input control wrapped in a UIScrollView ( using inheritance). A UIScrollView works by moving it's contents around using the co-ordinates of it's view around relative to it's frame.
Look at the contentOffset of the UITextView to get the amount of vertical scrolling that has occurred ( the text has scrolled up, so the y value will be negative.)
Once you have the amount of scrolling, you need to get the font for the UITextView. Use NSString sizeWithFont to get the height of a line. Divide the y-coordinate by the line height and that will give you how many newlines to skip.
The end of the visible text is a little different. Depending on your controller structure, the UITextView may have been resized, or not. If you're using a UITableViewController, for example, it will typically resize the tableView automatically. I'm going to assume that you have resized the UITextView, in which case the end 'y' is the start 'y' + the textView.frame.size.height. If you haven't resized the UITextView to fit the space above the keyboard, then you change the design to do so, or subtract the size of the on screen keyboard.
Hope this helps

Resources