Add a label after a String - swift

I need to create a line of text with two colors
There will Be a text, which is string in black and there will be one $ Symbol and it should be red.
lazy var dollarSmb: UILabel = {
let smb = UILabel()
smb.text = "$"
smb.font = UIFont.systemFont(ofSize: 17, weight: .regular)
smb.textColor = UIColor.red
smb.baselineAdjustment = .alignCenters
smb.translatesAutoresizingMaskIntoConstraints = false
return smb
}()
And I want to add it after the label string, something like that:
Var label = "This is a test" + " \(dollarSmb)"
It's not working
Could anyone help me the best way to do that?
Many thanks

You could use NSAttributedString to construct a single string with a different color.
let attributedString = NSMutableAttributedString(string: "This is a test ")
let dollarSymbl = NSAttributedString(string: "$", attributes: [.foregroundColor: UIColor.red])
attributedString.append(dollarSymbl)
// Then assign it to a UILabel
label.attributedText = attributedString

Use an NSAttributedString and instead of setting smb.text, set smb.attributedText.
Something like
smb.attributedText = NSAttributedString(string: "$", attributes [.foregroundColor: UIColor.red])

Related

Swift attribute for new line in NSAttributedString

I have a UITextView with a lightGray text.
I would like the color to always be set to black with each new line so that I can be sure that the new line is always black regardless of the color of the previous line
For example
This is first line --> foregroundColor.lightgray
\n
_ --> this new empty line must have foregroundColor.black
To do this I tried to change the foregroundColor attribute every time I hit enter (new line \n)
In Coordinator of UITextView
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
let customAttrributes : [NSAttributedString.Key: Any] = [
NSAttributedString.Key.foregroundColor: UIColor.black
]
if textView.selectedTextRange != nil {
textView.textStorage.addAttributes(customAttrributes, range: NSRange(location: textView.selectedRange.location, length: 1))
This return an "Out of bounds" error and I don't understand why. I suppose it is due to the fact that since there is no character, length 1 is considered non-existent. But then is it possible to set the new blank line already with the black text attribute or do you have to wait for some characters to be inserted?
Thanks!
One of easiest way to do it is to set typingAttributes. You can detect a new line using this answer for example. So let's say what we started printing with .lightGray color. Firstly we set: textView.typingAttributes = [.foregroundColor: UIColor. lightGray]. We should switch to the black color on a start of a new line.
var previousRect = CGRect.zero
func textViewDidChange(_ textView: UITextView) {
let pos = textView.endOfDocument
let currentRect = textView.caretRect(for: pos)
self.previousRect = self.previousRect.origin.y == 0.0 ? currentRect : self.previousRect
if currentRect.origin.y > self.previousRect.origin.y {
textView.typingAttributes = [.foregroundColor: UIColor.black]
}
self.previousRect = currentRect
}
This is an example for two line with different text and textColor in NSAttributedString:
let attributedString = NSMutableAttributedString(attributedString: NSAttributedString(string: "First Line", attributes: [.font: UIFont.systemFont(ofSize: 16, weight: .semibold), .foregroundColor: UIColor.lightGray]))
attributedString.append(NSAttributedString(string: "Second Line", attributes: [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 16, weight: .semibold)]))
textView.attributedText = attributedString

SKLabelNode Border and Bounds Issue

I am attempting to create text that has an outline. I am currently using SKLabelNode with NSAttributedString, which you can now do in SpriteKit as of iOS 11. The problem is, if the stroke width is too thick, then the outline gets cut off by what appears to be the bounding rectangle of the SKLabelNode. Please see below for the image and code.
extension SKLabelNode {
func addStroke(_ strokeColor:UIColor) {
let font = UIFont(name: self.fontName!, size: self.fontSize)
let attributes:[NSAttributedStringKey:Any] = [.strokeColor: strokeColor, .strokeWidth: 20.0, .font: font!]
let attributedString = NSMutableAttributedString(string: " \(self.text!) ", attributes: attributes)
let label1 = SKLabelNode()
label1.horizontalAlignmentMode = self.horizontalAlignmentMode
label1.text = self.text
label1.zPosition = -1
label1.attributedText = attributedString
self.addChild(label1)
}
}
I looked at expanding the frame of the SKLabelNode serving as the border text, but that is a get-only property. I tried to add leading/trailing spaces, but they appear to be automatically trimmed. Using a negative value for strokeWidth works but creates an inner stroke, I'd prefer to have an outer stroke.
Any ideas? Thanks in advance for the help!
Mike
You shouldn't need to create a separate node for the stroke.
Use negative width values to only render the stroke without fill.
Use .foregroundColor to fill.
You should first check to see if an attributed string is already present to ensure you do not clobber it.
Here is the code:
extension SKLabelNode {
func addStroke(color:UIColor, width: CGFloat) {
guard let labelText = self.text else { return }
let font = UIFont(name: self.fontName!, size: self.fontSize)
let attributedString:NSMutableAttributedString
if let labelAttributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelAttributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
let attributes:[NSAttributedStringKey:Any] = [.strokeColor: color, .strokeWidth: -width, .font: font!, .foregroundColor: self.fontColor!]
attributedString.addAttributes(attributes, range: NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}

center and bold TextView swift

Hi all I am trying to set a bold and centre to my text view I have 3 different colours in the view but I want the 2 colours that change to be centred. Is there a way to do this? below is my code.
let myString:String = DisplayableContents.texts[10]
var myMutableString = NSMutableAttributedString()
myMutableString = NSMutableAttributedString(string: myString, attributes: [NSFontAttributeName:UIFont(name: "Calibri", size: 17.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSRange(location:74, length:96))
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.gray, range: NSRange(location:96, length:19))
// set label Attribute
infoBox.attributedText = myMutableString
Try with
let myString:String = DisplayableContents.texts[10]
var myMutableString = NSMutableAttributedString()
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Center
myMutableString = NSMutableAttributedString(string: myString, attributes: [NSParagraphStyleAttributeName:paragraphStyle, NSFontAttributeName:UIFont(name: "Calibri", size: 17.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSRange(location:74, length:96))
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.gray, range: NSRange(location:96, length:19))
// set label Attribute
infoBox.attributedText = myMutableString
But 'Calibri' doesn't exist in iOS. You can check fonts in http://iosfonts.com/. If you are adding the font to your project check its bold variation, probably 'Calibri-Bold'

How to set alignment for WKInterface Label using setAttributedText

I'm trying to set alignment for WKInterfaceLabel using setAttributedText function. Here is my code:
var paragraphStyle = NSParagraphStyle.defaultParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.Center
var attributedDictonary = [NSForegroundColorAttributeName:UIColor.greenColor(), NSParagraphStyleAttributeName:paragraphStyle]
var attributeString = NSAttributedString(string: "TextAttributed", attributes: attributedDictonary)
self.titleLabel.setAttributedText(attributeString)
But I got a problem with this line:
paragraphStyle.alignment = NSTextAlignment.Center
I got error: Cannot assign to 'alignment' in 'paragraphStyle'
How to set alignment for WKInterfaceLabel using setAttributedText?
You need to use NSMutableParagraphStyle:
var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.CenterTextAlignment

is it possible to set the UILabel distance between the line?

Is it possible to set a UILabel's distance between the line, as i had a UILabel contain 3 lines, and linebreakmode is wordwrap?
If you're referring to "leading", which refers to the gap between lines of type - you cannot change this on a UILabel. That is inferred from the front of the label itself. Some people have tried to create categories to override the "leading" property of the UIFont for the label but it doesn't actually work when rendering.
If you really need to control the vertical spacing between lines of text then your best bet is to programmatically drop 1 UILabel per line of fixed width and control the vertical gap yourself.
Here is how you can set line spacing using interface builder and programatically as well.
From Interface Builder:
Programmatically:
SWift 4
Using label extension
extension UILabel {
// Pass value for any one of both parameters and see result
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "is\nit\npossible\nto\nset\nthe\nUILabel\ndistance\nbetween\nthe\nline?"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "is\nit\npossible\nto\nset\nthe\nUILabel\ndistance\nbetween\nthe\nline?"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString