SKLabelNode - how to center align when more than one line? - ios

With SKLabelNode, it would appear that when you break to more than one line,
the results is always
abcde
fg
rather than
abcde
fg
Really it seems that SKLabelNode is just left-aligned, and that's it.
Is there a solution - how to make multiline SKLabelNode center-align?
Note - horizontalAlignmentMode is totally unrelated. it simply allows you to choose whether the anchor of the overall label area is on the left, right or center of the position.

I solved this issue by setting attributedText to SKLabelNode. Seemed like the easiest way to do it, hope Apple fixes this issue soon.
Swift 4
let attrString = NSMutableAttributedString(string: yourString)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
let range = NSRange(location: 0, length: yourString.count)
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: range)
attrString.addAttributes([NSAttributedStringKey.foregroundColor : UIColor.black, NSAttributedStringKey.font : UIFont.systemFont(ofSize: 30)], range: range)
yourLabelNode.attributedText = attrString

It seems that Apple's SKLabel simply does not center multi-line text. (As of 2018.)
The behavior can only be described as broken - the second and latter lines just flush left no matter what setting.
One solution is to use a "second label", example below.
Later...
#MartinŠkorc seems to have discovered you can use AttributedString with SKLabels - so, great! Thanks Martin!
import SpriteKit
class StupidMultilineSKLabelNode: SKLabelNode {
// Apple's SKLabel does not center multi-line text
// this class works around the problem by making
// a "sub" SKLabel for the second line
// if the .text includes a newline, a line break,
// this class will present it as a two-line SKLabel,
// but properly centered (each line itself centered).
// (this example allows just the one extra line)
// please note,
// this is not meant to be a generalized class;
// rather it is meant to work quick in a specific case.
// you can change it as needed
// using a "second label" does seem to be the only solution
// until Apple address the issue
var stupidExtraLabel: SKLabelNode
override init() {
stupidExtraLabel = SKLabelNode()
super.init()
stupidExtraLabel.basicSettings()
// the simplest approach: in "basicSettings" simply set
// your point size, font, color, etc etc as you wish
// just always use that call to set all labels in the project
stupidExtraLabel.position = CGPoint(x: 0, y: -10)
stupidExtraLabel.text = ""
self.addChild(stupidExtraLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var alpha: CGFloat {
didSet {
super.alpha = alpha
stupidExtraLabel.alpha = alpha
}
}
override var fontColor: UIColor? {
didSet {
super.fontColor = fontColor
stupidExtraLabel.fontColor = fontColor
}
}
override var text: String? {
didSet {
let lines: [String] = text!.components(separatedBy: ["\n"])
super.text = ""
stupidExtraLabel.text = ""
if lines.count > 0 { super.text = lines[0] }
if lines.count > 1 { stupidExtraLabel.text = lines[1] }
stupidExtraLabel.position = CGPoint(x: 0, y: -10)
}
}
}

Following up - I posted a link instead of code, which is kind of a no-no. I don't have a big rep (noob), so I also can't edit yet :)
I recently discovered that you can overlay UIKit on top of scenekit (probably Sprite Kit too). I've tried it and it works with no loss in FPS, so I'm removing all of my Spritekit overlays (menus/labels) and using the UIKit basics (UIButton, UILabel). If this is of interest, I can share some code. I'm still figuring things out, but far enough into it that I think it's going to work.

Related

iOS 13: How can I tweak the leading / descend / line height of a custom font in UIKit / SwiftUI

I'm using a custom font and somehow the rendering screws up the line height, potentially because of misconfigured descent or leading (?), so that g's and j's are cut off in the last line of the rendered text. I think it might be a problem with this particular font, because Sketch is also exposing similar issues with the font in question, but I feel like I don't understand quite enough about typographic measurements or fonts. I found this Apple documentation page on Typographic Concepts quite insightful.
I looked into the font itself with the test version of FontLab, which I have used for the first time btw - so I've little clue really what I'm looking at. It does seem like the g is going below the configured descent, which seems to be what the last line is. (?) (See: Character view in FontLab, showing the descend of the g)
Via lineSpacing I could adjust the distance between just the lines itself to fix this in the first few lines. I know iOS 14 is going to bring a way to modify the leading of a Text in SwiftUI. But I need to target iOS 13, so that doesn't help.
I've also tried SwiftUI's Text, a normal UILabel.text and UILabel.attributedText with a customized paragraph style, but nothing I adjust there seems to mitigate the problem.
The view is not even clipping. Just adding padding to the frame does not help at all. It increases the distance, but the g's and j's are still cut.
What can I do? Subclass UILabel and overwrite the intrinsicContentSize to add some extra space, when there is a g and j in the last line? That feels a) dirty and b) given that padding didn't help, it might not fix the problem?
Is the font itself the problem here? Can I patch the font somehow without making it worse?
Is there any way to modify the leading or the descend height of the font, when I use lower level APIs? Seems like I could go down to CoreText, as CTFontCreateCopyWithAttributes(_:_:_:_:) is a candidate, if I could just modify via attributes the leading, line space or the descend? Can or monkey-patch / swizzle things without shooting myself in the knee? Should I just file a radar a feedback?
You need to use NSAttributedString instead of String to control the line spacing of UILabel. Here is sample code
let style = NSMutableParagraphStyle()
style.lineSpacing = 20
let string = NSMutableAttributedString(string: "The quick brown fox jumps over the lazy dog, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog")
string.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, string.length))
let label = UILabel(frame: CGRect(x: 20, y: 100, width: 300, height: 500))
label.attributedText = string
label.numberOfLines = 0
self.view.addSubview(label)
Out put
I know what you are asking as I have faced the same issues with custom fonts. I am going to offer two solutions. In my own project I went the way of your suggestion in overriding intrinsicContentSize and adding a padding multiplier for height and width. In my case the fonts were user facing so I had a struct that held all the relevant information. FYI Chalkduster is in the system and clips. I also believe that this is all due to the font file itself.
Solution 1:
Example:
struct UserFont{
var name : String
var displayName : String
var widthMultiplier : CGFloat
var heightMultiplier : CGFloat
}
Then in my UILabel I have it subclassed to use both of these metrics
#IBDesignable
class MultiplierUILabel: UILabel {
#IBInspectable var widthPaddingMultiplier : CGFloat = 1
#IBInspectable var heightPaddingMultiplier : CGFloat = 1
override var intrinsicContentSize: CGSize{
return CGSize(width: super.intrinsicContentSize.width * widthPaddingMultiplier, height: super.intrinsicContentSize.height * heightPaddingMultiplier)
}
}
This to me was the simplest implementation as I found the font and multiplier scale accordingly.
Solution 2:
You might be able to get the draw to occur slightly higher by measuring the glyph bounds and adjusting the origin y. For example this fixes the clipping on Chalkduster font that is included in the system.
#IBDesignable
class PaddingUILabel: UILabel {
override func drawText(in rect:CGRect) {
//hello
guard let labelText = text else { return super.drawText(in: rect) }
//just some breathing room
let info = boundsForAttrString(str: labelText, font: self.font!, kern: .leastNormalMagnitude)
let glyph = info.glyph
var newRect = rect
let glyphPadding = -(glyph.origin.y)
if glyphPadding - info.descent > 1 && info.descent != 0{
newRect.origin.y -= glyphPadding/2
}else{
if info.descent != 0{
newRect.origin.y += (info.descent - glyphPadding)/2
}
}
super.drawText(in: newRect)
}
func boundsForAttrString(str:String,font:UIFont,kern:CGFloat)->(glyph:CGRect,descent:CGFloat){
let attr = NSAttributedString(string: str, attributes: [.font:font,.kern:kern])
let line = CTLineCreateWithAttributedString(attr)
var ascent : CGFloat = 0
var descent : CGFloat = 0
var leading : CGFloat = 0
CTLineGetTypographicBounds(line, &ascent, &descent, &leading)
let glyph = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds).integral
return (glyph,leading != 0 ? descent : 0)
}
}
Result of Solution 2:
System
PaddingUILabel using glyph bounds

Is it possible to set the alignment of segmented Control titles to the left?

I have been looking around for a way to set the alignment of the segmented control titles to the left but I don't seem to be able to achieve what I want.
I have created this little function to change the frame of the subviews of the segment control.
It works at first.
func modifyFrameOfSegment() {
for segment in segmentedControl.subviews {
guard segment.subviews.isNotEmpty else { return }
segment.contentMode = .left
for label in segment.subviews where label is UILabel {
label.frame = CGRect(x: 0, y: label.frame.origin.y, width: label.frame.size.width, height: label.frame.size.height)
(label as! UILabel).textAlignment = .left
}
}
}
But everytime I select a new segment it resets the frames of all the subviews and center align all the titles again.
Is there a way to achieve a permanent left alignment for the segment titles in a segmented control?
Any tips or advice would be greatly appreciated.
Thank you for your time.
Let's use this method
self.segmentedControl.setContentPositionAdjustment(UIOffset(horizontal: -20, vertical: 0), forSegmentType: .left, barMetrics: .default)
And you can do what you want (Of course, you can change the horizontal & vertical value by your needs). Here is the result:
Update:
There's apparently no way to set the alignment of the items, but you can fake it by adjusting the position of each individual item using setContentOffset(_ offset: CGSize, forSegmentAt segment: Int). Here's a kludgy example:
class LeftSegmentedControl: UISegmentedControl {
var margin : CGFloat = 10
override func layoutSubviews() {
super.layoutSubviews()
leftJustifyItems()
}
func leftJustifyItems() {
let fontAttributes = titleTextAttributes(for: .normal)
let segments = numberOfSegments - 1
let controlWidth = frame.size.width
let segmentWidth = controlWidth / CGFloat(numberOfSegments)
for segment in 0...segments {
let title = titleForSegment(at: segment)
setWidth(segmentWidth, forSegmentAt: segment)
if let t = title {
let titleSize = t.size(withAttributes: fontAttributes)
let offset = (segmentWidth - titleSize.width) / 2 - margin
self.setContentOffset(CGSize(width: -offset, height: 0), forSegmentAt: segment)
}
}
}
}
Here's what it looks like:
There are a few caveats:
This version sets the segments to all have equal width, which might not be what you want.
I used a fixed left margin of 10px because it seems unlikely that you'd want to vary that, but you can obviously change it or make it a settable property.
Just because you can do this doesn't mean you should. Personally, I don't think it looks great, and it suffers in the usability department too. Users expect segmented control items to be centered, and left-justifying the items will make it harder for them to know where to tap to hit the segment. That seems particularly true for short items like the one labelled "3rd" in the example. It's not terrible, it just seems a little weird.
Original answer:
UIControl (of which UISegmentedControl is a subclass) has a contentHorizontalAlignment property that's supposed to tell the control to align its content a certain way, so the logical thing to do would be to set it like this:
let segmented = UISegmentedControl(items: ["Yes", "No", "Maybe"])
segmented.frame = CGRect(x:75, y:250, width:250, height:35)
segmented.contentHorizontalAlignment = .left
But that doesn't work — you still get the labels centered. If you've got a compelling use case for left-aligned segments, you should send the request to Apple.
One way you could work around this problem is to render your labels into images and then use the images as the segment labels instead of plain strings. Starting from the code in How to convert a UIView to an image, you could easily subclass UISegmentedControl to create images from the item strings.

UILabel with Paragraph Style Line Spacing

I'm trying to create a messaging application and am encountering a very strange issue.
The reason there is so much space between "Thomas" and the bottom of the text bubble is becasue the UILabel is creating another line. Currently I'm setting the label's text using the attributedText property, and passing in a NSMutableParagraphStyle with a line spacing of 8. If I set the line spacing to 0, the space between "Thomas" and the bottom of the text bubble goes away like so:
Here's where it gets strange though. If I set the paragraph line spacing back to 8, and add a couple more characters to the line, the text bubble appears without the extra line:
All help is greatly appreciated :)
Here is my code:
class MessageTableViewCell: UITableViewCell {
var didSetupConstraints = false
var thumbnail = UIImageView.newAutoLayoutView()
let messageTailIcon = UIImageView.newAutoLayoutView()
var messageView = UIView.newAutoLayoutView()
var messageLabel = UILabel.newAutoLayoutView()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
thumbnail.image = UIImage(named: "ThomasBaldwin")
thumbnail.layer.cornerRadius = 17.5
thumbnail.clipsToBounds = true
messageTailIcon.image = UIImage(named: "MessageTailIcon")
messageView.backgroundColor = Application.greyColor
messageView.layer.cornerRadius = 10
let paragraphStyle = NSMutableParagraphStyle.new()
paragraphStyle.lineSpacing = 8
messageLabel.numberOfLines = 0
messageLabel.layer.cornerRadius = 10
messageLabel.attributedText = NSMutableAttributedString(
string: "Thomas says hello",
attributes: [
NSFontAttributeName: UIFont(name: "AvenirNextLTPro-Regular", size: 12.5)!,
NSForegroundColorAttributeName: UIColor.colorFromCode(0x262626),
NSBackgroundColorAttributeName: Application.greyColor,
NSKernAttributeName: 0.5,
NSParagraphStyleAttributeName: paragraphStyle
]
)
contentView.addSubview(thumbnail)
contentView.addSubview(messageView)
messageView.addSubview(messageTailIcon)
messageView.addSubview(messageLabel)
updateConstraints()
}
override func updateConstraints() {
if !didSetupConstraints {
thumbnail.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
thumbnail.autoPinEdgeToSuperviewEdge(.Leading, withInset: 8.5)
thumbnail.autoSetDimensionsToSize(CGSize(width: 35, height: 35))
messageView.autoPinEdgeToSuperviewEdge(.Top, withInset: 17.5)
messageView.autoPinEdge(.Leading, toEdge: .Trailing, ofView: thumbnail, withOffset: 10)
messageView.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 24.5)
messageView.autoPinEdgeToSuperviewEdge(.Bottom)
messageTailIcon.autoPinEdgeToSuperviewEdge(.Top, withInset: 15)
messageTailIcon.autoPinEdgeToSuperviewEdge(.Leading, withInset: -10)
messageTailIcon.autoSetDimensionsToSize(CGSize(width: 18, height: 9))
messageLabel.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsets(top: 8.5, left: 10, bottom: 8.5, right: 5), excludingEdge: .Trailing)
messageLabel.autoPinEdgeToSuperviewEdge(.Trailing, withInset: 0, relation: .GreaterThanOrEqual)
didSetupConstraints = true
}
super.updateConstraints()
}
}
If you would like to view a sample project demonstrating the issue, I've pushed one to github
Okay, so finally locked down and easy answer, this has to do with your KERNING attributed only. watch this:
Also disregard the sizing of the red cell, this is NOT happening like this in the app, this is just a product of my screenshots being different sizes, but please do try this for yourself. Comment out the kerning and the reapply it and you'll see the same thing
with kerning with "Thomas"
without kerning with "Thomas"
with kerning with "Thomas says hello"
without kerning with "Thomas says hello"
I've done everything possible to check the code, use different constraints, and I even played around with ALL options of an NSAttributedString, and the only thing that changes this bad behavior is the kerning attribute, and it's doing this to all types of fonts, not just Avenir. In fact, the font you used in this example is system font when you didn't set a font at all, but I've tried it with 3 fonts now, same effect, the kerning seems to be broken or perhaps its working as intended for Swift and/or ObjC, but I think this is actually a bug.
Most NSAttributedString options, if you want to mess around with stuff:
var myString1 = NSMutableAttributedString(string:"Thomas asdfadsf asdfasdfasdf asdfasdf asdfasdf \n asdfasdf asdf \n")
let myString1Font1 = UIFont.systemFontOfSize(12.0)
let originalNSString = myString1.string as NSString
let myString1Range1 = originalNSString.rangeOfString(myString1.string)
var myString1ParaStyle1 = NSMutableParagraphStyle()
myString1ParaStyle1.alignment = NSTextAlignment.Natural
myString1ParaStyle1.baseWritingDirection = NSWritingDirection.Natural
myString1ParaStyle1.defaultTabInterval = 0.0
myString1ParaStyle1.firstLineHeadIndent = 0.0
myString1ParaStyle1.headIndent = 0.0
myString1ParaStyle1.hyphenationFactor = 0.0
myString1ParaStyle1.lineBreakMode = NSLineBreakMode.ByWordWrapping
myString1ParaStyle1.lineHeightMultiple = 0.0
myString1ParaStyle1.lineSpacing = 8.0
myString1ParaStyle1.maximumLineHeight = 0.0
myString1ParaStyle1.minimumLineHeight = 0.0
myString1ParaStyle1.paragraphSpacing = 0.0
myString1ParaStyle1.paragraphSpacingBefore = 0.0
myString1ParaStyle1.tailIndent = 0.0
myString1.addAttribute(NSKernAttributeName, value:0.5, range:myString1Range1)
myString1.addAttribute(NSFontAttributeName, value:myString1Font1, range:myString1Range1)
myString1.addAttribute(NSParagraphStyleAttributeName, value:myString1ParaStyle1, range:myString1Range1)
myString1.addAttribute(NSBackgroundColorAttributeName, value:UIColor.redColor(), range:myString1Range1)
myString1.addAttribute(NSForegroundColorAttributeName, value:UIColor.blackColor(), range:myString1Range1)
Again, this isn't an constraints issue, I was wrong, this is only a KERNING issue, and this sucks, but such is life, perhaps this needs to be reported to RADAR.
Also, you can try this for yourself, anything BUT a 0 or 0.00000 or as many zeros as you want will produce the wrong results with Kerning, i tried this and it messes up your label field the same way that kerning would mess up the field with a larger value:
NSKernAttributeName: 0.00000000000001
HOLD up, I solved it, from what it looks like, set this value, just add this to your paragraphStyle variable that you set up in the example project, its working with the kerning, not sure if this is working for all fonts, but it fixes your example project at least:
paragraphStyle.lineHeightMultiple = 1.5
The only problem with this method is that it works for lines with one word or one line, you'll have to do a word count adjustment to set this "lineHeightMultiple" based on when a new line appears, this sucks, but it works, obviously, not a very good method to use, but works if you have a 1 liner string, needs adjusting if you have more, otherwise just turn off kerning, and it will be solved wihout this line height multiple.
It's as if the line height is changing internally and pushing characters to a new line but apple isn't automatically accounting for this change in character width.
And as a matter of fact, I think the answer you are looking for isn't kerning at all but tracking, which will push the letters apart from each other. The problem with kerning is that kerning screws around with the glyphs of the fonts and overrides some of their behaviors and as such it can be anoticeable effect like we are seeeing here.
From Apple:
preferredFontForTextStyle:, the specific font returned includes traits
which vary according to user preferences and context, including
tracking (letter-spacing) adjustments, in addition to being tuned for
the use specified by the particular text style constant. The fonts
returned using text style constants are meant to be used for all text
in an app other than text in user interface elements, such as buttons,
bars, and labels. Naturally, you need to choose text styles that look
right in your app. It’s also important to observe the
UIContentSizeCategoryDidChangeNotification so that you can re–lay out
the text when the user changes the content size category. When your
app receives that notification, it should send the
invalidateIntrinsicContentSize message to views positioned by Auto
Layout or send setNeedsLayout to user interface elements positioned
manually. And it should invalidate preferred fonts or font descriptors
and acquire new ones as needed.
https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/TypoFeatures/TextSystemFeatures.html
If you truly need kerning, then you should probably be tweaking the kerning values of the ligatures if the font has any available to play with.
Other things to consider, this does work, but it's also bold so it's already not something that matches your style above, but it's something you can toy around with:
let sytemDynamicFontDescriptor = UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleHeadline)
let size = sytemDynamicFontDescriptor.pointSize
let myString1Font1 = UIFont(descriptor: sytemDynamicFontDescriptor, size:size)
println(sytemDynamicFontDescriptor.fontAttributes())
messageLabel.numberOfLines = 0
messageLabel.layer.cornerRadius = 10
messageLabel.attributedText = NSMutableAttributedString(
string: "Thomas asdfad as ",
// string: "Thomas says hello", // switch back to this to see it display the text properly on one
attributes: [
NSFontAttributeName: myString1Font1,
NSForegroundColorAttributeName: UIColor.blackColor(),
NSBackgroundColorAttributeName: UIColor.redColor(),
NSKernAttributeName: 0.5,
NSParagraphStyleAttributeName: paragraphStyle
]
)

Space characters being removed from end of String - UILabel Swift

I have the following code for a Table View Cell in Swift
let rcap = cell.viewWithTag(613) as! UILabel
rcap.text = "Capacity: \(room.capacity) " // I added space at the end
The space characters at the end of the string, are removed when shown on screen.
If I add space characters at the beginning of the string there is no issue.
At the moment I am using this 'full stop' hack, but it is not good enough:
rcap.text = "Capacity: \(room.capacity) ."
Any ideas?
I also tried:
rcap.text = "Capacity: \(room.capacity) " + " "
Adding a constraint to the label seems like the better solution to me.
It allows you to define a well-defined distance between the label and
the margin of the table view cell.
The width of a space is dependent on the font and might even change if the text in the label is shrunk, causing non-aligned texts in the
table view.
Having said that, you can prevent the trailing space from being
removed by appending a "ZERO WIDTH NON-JOINER" character (U+200C):
rcap.text = "Capacity: \(room.capacity) \u{200c}"
But I consider that more as a "trick" than the proper solution to the
problem.
Update: It seems that this "trick" does not work any more in iOS 10,
so a layout constraint should be used instead, as initially suggested.
For 2020
This issue is critical when working with monospaced fonts and doing layout, such as, say, user codes which may have alignment spaces at the end in monospace.
\u{200c} does seem to work perfectly:
Please note that the solution of #MartinR does in fact work perfectly, today, 2020 A.D., iOS 13, Xcode 11.
.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"
.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"
.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"
You can now absolutely normally set font sizes, etc etc. and it all works properly.
Bonus code sample!
Here's a simple UILabel that pads it out, so you need do nothing else:
class PaddyLabel: UILabel {
// pad always to 20 characters...
override var text: String? {
get {
return super.text
}
set {
if newValue == nil {
super.text = nil
return
}
var t = newValue!
while t.count < 20 { t += " " }
t += "\u{200c}"
super.text = t
}
}
So in the above three yellow examples, you would just do this
.text = "FATTIE KODE " + reservation
and not have to bother adding the needed spaces manually.
Note that even if you are not using monospace fonts, a typical real-world use case is when you want to "pile together" UILabels - imagine them being, say, one word each - and have the absolutely correct space between them regardless of font size etc, that is to say as if it's just the one sentence in the one UILabel.
The only way to actually do that is to have UILabel "actually include the space".
If it does not work in a future iOS...
Perhaps this will (again?) break in a future iOS.
The only other solution I know is this. To begin with, it's ridiculously hard to just add padding to a UILabel. It is explained here:
Adding padding manually to a UILabel?
How to actually reliably add damned padding to a UILabel
In fact, using a similar technique, it would be possible to force the extra width on one end using intrinsicContentSize , drawText and textRect. To know how much width to add, you would have to calculate that using a phantom example text, with the number of characters in question. Doing that calculation would call for the usual annoying techniques for calculating likely text rendering size. But because that sucks, fortunately we can use the amazing tip of #MartinR (as usual!)
I have created custom class for UILabel, take a look:
import UIKit
#IBDesignable class CustomLable: UILabel {
#IBInspectable var topInset: CGFloat = 5.0
#IBInspectable var bottomInset: CGFloat = 5.0
#IBInspectable var leftInset: CGFloat = 7.0
#IBInspectable var rightInset: CGFloat = 7.0
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets.init(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
super.drawText(in: rect.inset(by: insets))
}
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(width: size.width + leftInset + rightInset,
height: size.height + topInset + bottomInset)
}
}
You can than assign a class to UILabel from Storyboard and provide space you need.
Try putting zero-width space instead of the period. It can be written using left Alt and 0173 on numeric keyboard. Or you can copy it here and delete the quotes: "­"
So your code for setting the text will look like this (with the zero-width space at the end):
rcap.text = "Capacity: \(room.capacity) ­"
Non-breaking space (\u{00a0}) should work too and its usage is as \u{200c}'s in Martin's and Fattie's answer
rcap.text = String.localizedStringWithFormat("Capacity: %# ", rrom.capacity)
try above code it may works

Inset text in UILabel from left

I have a UILabel which I am using to display multiple lines of text. At the moment when the text is displayed, it is right up against the left hand side of the label which doesn't look too great. I would like the text to be inset slightly from the left.
This is my code so far:
if notes.objectAtIndex(indexPath.row) as NSString == "" {
cell.notesLabel.text = "No notes to display."
cell.notesLabel.textAlignment = NSTextAlignment.Center
} else {
cell.notesLabel.textAlignment = NSTextAlignment.Left
}
I was looking at some Objective-C examples but I couldn't get them to work and I don't really think they were what I was looking for.
Also, I was trying to do the same thing with a different label and in that case I assumed I could have just added " " to the end of the string (as it is a single line label) to move it in from the right, but I was surprised to see that this doesn't work?
Thanks.
To inset the text from the left edge, you should create a UILabel subclass, and override drawTextInRect:,
class RDLabel: UILabel {
override func drawTextInRect(rect: CGRect) {
let newRect = CGRectOffset(rect, 10, 0) // move text 10 points to the right
super.drawTextInRect(newRect)
}
}

Resources