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.
Related
Using autolayout to have a multiline UILabel auto size the text to fit does not work for single words.
Here is how storyboard is set up:
Here's the problem.
This does not display properly:
But this does:
I have adjusted every setting in the storyboard. I have changed all of the Line Break settings (wrap, truncate, etc), I have adjusted # of lines, I have made text plain vs attributed, I've changed font sizing and scaling, everything. What am I missing? Why does "California" get cut off instead of shrinking to fit? I've seen many other posts on SO and haven't yet found a solution (which needs to be compatible back to iOS 9)
Your label is being filled both horizontally and vertically until it runs out of space, then it starts shrinking the text to fit. In the one word example it breaks the word into two lines because there is vertical room.
Do you know in advance or can you calculate in the app when you have only one word in this label? If so you can change the number of lines to 1 instead of 0 so the app will keep the contents on one line and shrink this word.
This is an issue with UILabel in iOS7 and iOS8, it does not
present in iOS9. This odd UILabel behaviour is experienced with
different fonts, in Xcode versions 6 and 7 with Swift, using the
simulator and device.
Problem:
I have a UILabel that has a center text alignment. At different font sizes, some lines of text stop being center aligned and snap to left alignment. It is subtle but noticeable.
In the images below:
LEFT: all lines of text are centered neatly.
MIDDLE: after increasing the font size, the third line from the top snaps more to the left instead of remaining centered. (Notice more blue space on right.)
RIGHT: after increasing the font size a little more, both the second and third line from the top snap to the left instead of remaining centered. (Notice more blue space on right.)
Questions:
What explains what might be the cause of this unusual alignment behaviour in iOS7 and iOS8 but not iOS9?
How can I ensure that all lines are forced to remain center aligned perfectly regardless of the font type or font size used?
What is the bug fix or work around for this in iOS7 and iOS8 so that apps created using UILabel centre aligned don’t feature the bug?
Use UITextView
With all due respect, it is my experience that UILabel is plagued with bugs when it comes to multiple lines (Line count other than 1).
Starting, but not limited to sizing cells containing such labels hardly able to predict its footprint1.
Use UITextView, non editable, scrolling disabled (that is the key). You will achieve the same effects, with more control over the final appearance.
1 See note 3 on this Stack Overflow UILabel answer.
Is it expected that a multi-line UILabel with a custom lineSpacing attribute include that line spacing even when the label's text fits on one line?
Here is my label:
let label = UILabel()
label.numberOfLines = 4
var paragraph = NSMutableParagraphStyle()
paragraph.lineSpacing = 5
paragraph.lineBreakMode = .ByTruncatingTail
label.attributedText = NSAttributedString(string: "Some short text", attributes: [NSParagraphStyleAttributeName: paragraph])
And here is how it is laid out. Note the additional spacing below the text.
For comparison:
What's strange is the lack of consistency. When the label extends to a second line, the bottom line no longer includes this additional spacing:
Is there a way to remove this line spacing when there is a single line of text? Or some other way to enforce some consistency so I can at least account for it?
Update
The baseline calculation also seems broken. When attempting to align a view (here, the red box) with the label's baseline, multi-line labels are partially covered.
Since you said you were using a custom font, my best guess based on prior experience is that the root cause of that issue that you seeing lies somewhere inside of the custom font itself. Whenever I am given a custom font by a client, 90% of the time, something is "wrong" with the actual font metrics (as interpreted by Apple's internal font rendering subsystem, even though it might render correctly somewhere else).
The good news is that this is fixable, but it requires rebuilding the font with new metrics, which is usually a trial/error affair. You might also need to check to see if the license you have for the font will allow such a thing (if it even matters).
That being said, these are some resources to questions that I keep around for this exact scenario whenever I start a new project:
Here's a similar question to yours with the assumption that this is a custom font issue: "Custom UIFont baseline shifted". This question deals with this issue in a UIButton "UIButton custom font vertical alignment", but both of these questions end up at the answer to this question "Custom installed font not displayed correctly in UILabel".
I have a personal testbed app for custom fonts now that I use whenever I am first given a custom font. This allows me to test the font in isolation for each rebuild iteration to make sure it's perfectly rendering. Make sure to test your changes in various font sizes and even in additional languages (yes, lots of permutations). I have had issues specifically with Thai and Chinese when using custom fonts as their ascenders extend very close to the edge of the bounding box for a UILabel. The testbed that I've created for myself includes the font rendered in basic UILabels in various sizes and various languages in various sizes (since like I said, I've had a bad experience in the past with custom fonts in certain languages that rendered fine in Roman characters).
If someone has a better solution to this, I'd love to hear it as I run into this issue with custom fonts almost every time. This is my workflow for nipping the issue in the bud before we start compensating for the font's rendering issues during layout or using individual attributed string adjustments. I'm not font expert, I'm just a guy who likes fonts to render like the built-in fonts (especially when using auto layout).
You can calculate the number of lines and set lineSpacing to 0 if there's only one line.
But there might be a better solution.
paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping
can avoid this issue when text is multiline.
explicitly setting the font with with fontName [UIFont fontWithName:#"PingFangSC-Regular" size:14] , instead of using [UIFont systemFontOfSize:14] can avoid the issue when text is single line.
Hope this is helpful for you!
This is def. a issue for UILabel. It happens for custom as well as the system fonts.
If you can use a UITextView, go with that. The UITextView has no problems with single or multi line text line-spacing and behaves correctly (single line = no line spacing).
This way you can also avoid creating a custom line count func/ext.
Yes, the lineSpacing is applied regardless of how many lines are in the label. If you're using autolayout, you can work around this by constraining your label's baseline to its parent or sibling views (as appropriate), instead of the label's top edge aligned to the parent or sibling's top. (This assumes, however, that your label's background color is the same as the color of its parent view; otherwise, you'll see the extra line spacing appear in the background color.
Another thing you can do (and this is probably preferable, now that I think about it) is to set a paragraphSpacing attribute of 0 as well. That should negate the lineSpacing for the last line in the label, regardless of how many lines you have.
I have some ASCII syntax diagrams which must not have line breaks in the middle.
These don't have to be editable so I thought the best way is to use an UILabel with auto shrink option. But this option shrinks the text also if the content doesn't fit the height of the labels frame rectangle.
I just want to shrink only if the content doesn't fit the width. It would be absolutely fine to scroll vertically through the text.
What is the best way to do this with UILabel or any other UI element?
Use UITextView with 'editable' property set to false.
So let me rephrase your question. I guess what you want is a UILabel which can show multiple lines, but the longest line need to fit into the width of UILabel. If this is what you want, well the imagination is weird to me...
But anyway, I feel there's a conflict in your settings. First, allowing multiple lines implies you set "Lines" attribute (number of lines) as 0, which allows unlimited lines. But then Autoshrink will play no effect. I'm afraid it is not possible to be done by just setting the storyboard and instead, you need to write some code.
I guess people have raised related questions earlier, by which they want to dynamically change the font size when the text become too long. I guess you want to take a look about this:
Autoshrink on a UILabel with multiple lines
The last issue is you also want the scrolling effect (this is why I feel the outlooking will be weird.) But in short, to achieve this you need 1) dynamically change the UILabel height, most likely using the same technique as explained in the reference thread, and 2) wrap the UILabel in a scroll view. Maybe this can achieve what you want.
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)];