I\'m trying hard to find a way to simply add an outline/stroke/contour to my UILabel text. Talking about a stroke around the letters of the text not around the background of
Below is what I used in my App written in Swift 4.1
Swift 4.x
let strokeTextAttributes: [NSAttributedStringKey: Any] = [
NSAttributedStringKey.strokeColor: UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -3.0,
NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 18)
]
Update to Swift 5
This answer is built on Anandnimje and J.Doe answers, and is meant to update and streamline it to make the usage clearer and simpler.
Simply use these two functions:
func outline(string:String, font:String, size:CGFloat, outlineSize:Float, textColor:UIColor, outlineColor:UIColor) -> NSMutableAttributedString {
return NSMutableAttributedString(string:string,
attributes: outlineAttributes(font: UIFont(name: font, size: size)!,
outlineSize: outlineSize, textColor: textColor, outlineColor: outlineColor))
}
func outlineAttributes(font: UIFont, outlineSize: Float, textColor: UIColor, outlineColor: UIColor) -> [NSAttributedString.Key: Any]{
return [
NSAttributedString.Key.strokeColor : outlineColor,
NSAttributedString.Key.foregroundColor : textColor,
NSAttributedString.Key.strokeWidth : -outlineSize,
NSAttributedString.Key.font : font
]
}
Then use outline with your labels as the following:
label.attributedText = outline(string: "Label Text", font: "HelveticaNeue", size: 14, outlineSize: 4, textColor: .white, outlineColor: .black)
Here you have class with implementation, copy and paste to playgrond for test:
class StrokedLabel: UILabel {
var strockedText: String = "" {
willSet(newValue) {
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -4.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 30)
] as [String : Any]
let customizedText = NSMutableAttributedString(string: newValue,
attributes: strokeTextAttributes)
attributedText = customizedText
}
}
}
//////////// PLAYGROUND IMPLEMENTATION PART /////////
let text = "Stroked text"
// UILabel subclass initialization
let label = StrokedLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
// simple assign String to 'strockedText' property to see the results
label.strockedText = text
label.backgroundColor = UIColor.white
label
Swift 4.2
import UIKit
class StrokedLabel: UILabel {
var strockedText: String = "" {
willSet(newValue) {
let strokeTextAttributes : [NSAttributedString.Key : Any] = [
NSAttributedString.Key.strokeColor : UIColor.black,
NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.strokeWidth : -4.0,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 30)
] as [NSAttributedString.Key : Any]
let customizedText = NSMutableAttributedString(string: newValue,
attributes: strokeTextAttributes)
attributedText = customizedText
}
}
}
//////////// PLAYGROUND IMPLEMENTATION PART /////////
let text = "Stroked text"
// UILabel subclass initialization
let label = StrokedLabel(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
// simple assign String to 'strockedText' property to see the results
label.strockedText = text
label.backgroundColor = UIColor.clear
label
Maybe refactoring for this class will be welcomed, but should work for you at this form
As you can see usage is very convenient.
@anandnimje answer converted to Swift 4.2 and wrapped it into a function:
public func stroke(font: UIFont, strokeWidth: Float, insideColor: UIColor, strokeColor: UIColor) -> [NSAttributedStringKey: Any]{
return [
NSAttributedStringKey.strokeColor : strokeColor,
NSAttributedStringKey.foregroundColor : insideColor,
NSAttributedStringKey.strokeWidth : -strokeWidth,
NSAttributedStringKey.font : font
]
}
Usage:
label.attributedText = NSMutableAttributedString(string: "Hello World",
attributes: stroke(font: UIFont(name: "SourceSansPro-Black", size: 20)!,
strokeWidth: 4, insideColor: .white, strokeColor: .black))
Make sure you have the right name for your UIFont, else it crashes. Should never be a problem if you have the right name.
Your code works for me if I set the type of the attributes dictionary, like this:
let strokeTextAttributes: [String: Any] = [
// etc...
]
Maybe that's all your missing?
This code works for me.
let strokeTextAttributes = [
NSStrokeColorAttributeName : UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -4.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 30)
] as [String : Any]
myLabel.attributedText = NSMutableAttributedString(string: "Test me i have color.", attributes: strokeTextAttributes)
let strokeTextAttributes = [
NSAttributedString.Key.strokeColor : UIColor.red,
NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.strokeWidth : -4.0,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 30)]
as [NSAttributedString.Key : Any]
labelOutLine.attributedText = NSMutableAttributedString(string: "Your outline text", attributes: strokeTextAttributes)