UILabel with two different color text - ios

How can i have a UILabel with two different colors for the font? I will have text in two different strings and i want to make text with first string as red and second as green. The length of both the string is variable.

Try TTTAttributedLabel. It's a subclass of UILabel that supports NSAttributedStrings, which would make it easy to have multiple colors, fonts, and styles in the same string.
Edit: Alternatively, if you don't want the 3rd party dependency and are targeting iOS 6, UILabel now has the attributedText property.

You can't do this within a UILabels. But my suggestion is that instead of using multiple UILabel just concentrate on NSAttributedString. Find UIControllers that draw NSAttributedString because UILabel, UITextView do not support NSAttributedString.
PS: if you plan to distribute an iOS6 or later application, as UILabel now support NSAttributedString, you should use UILabel directly instead of OHAttributedLabel as it is now natively supported by the OS.

UILabel can only have one color. You either need a more sophisticated element, or - probably easier - just use two separate labels. Use [yourLabel sizeToFit]; and place them accordingly.

Swift 4
(Note: notation for attributed string key is changed in swift 4)
Here is an extension for NSMutableAttributedString, that add/set color on string/text.
extension NSMutableAttributedString {
func setColor(color: UIColor, forText stringValue: String) {
let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
}
}
Now, try above extension with UILabel and see result
let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let red = "red"
let blue = "blue"
let green = "green"
let stringValue = "\(red)\n\(blue)\n&\n\(green)"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: red) // or use direct value for text "red"
attributedString.setColor(color: UIColor.blue, forText: blue) // or use direct value for text "blue"
attributedString.setColor(color: UIColor.green, forText: green) // or use direct value for text "green"
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
Here is solution in Swift 3:
extension NSMutableAttributedString {
func setColorForText(textToFind: String, withColor color: UIColor) {
let range: NSRange = self.mutableString.range(of: textToFind, options: .caseInsensitive)
if range != nil {
self.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
}
}
}
func multicolorTextLabel() {
var string: NSMutableAttributedString = NSMutableAttributedString(string: "red\nblue\n&\ngreen")
string.setColorForText(textToFind: "red", withColor: UIColor.red)
string.setColorForText(textToFind: "blue", withColor: UIColor.blue)
string.setColorForText(textToFind: "green", withColor: UIColor.green)
labelObject.attributedText = string
}
Result:

In iOS 6 UILabel has NSAttributedString property. So use that.

Related

NSAttributedText alignment right and left doesn't work for the same object

I have a simple extension for NSAttributedString:
convenience init(
string: String,
strikeThrough: Bool = false,
color: UIColor? = nil,
font: UIFont? = nil,
alignment: NSTextAlignment? = nil
) {
var attributes = [NSAttributedString.Key: Any]()
if strikeThrough {
attributes[.strikethroughStyle] = NSUnderlineStyle.single.rawValue
}
if let color = color {
attributes[.foregroundColor] = color
}
if let font = font {
attributes[.font] = font
}
if let alignment = alignment {
let style = NSMutableParagraphStyle()
style.alignment = alignment
attributes[.paragraphStyle] = style
}
self.init(string: string, attributes: attributes)
}
And this is how I use it in code:
let baseString = "Collectives™ helps you find trusted answers faster, engage with product experts, and share knowledge around the technologies you use most."
let baseColor: UIColor.mineShaft
let baseFont = UIFont.poppinsRegular.withSize(16)
let attributedString = NSMutableAttributedString(string: baseString, color: baseColor, font: baseFont)
attributedString.append(NSAttributedString(string: "\n"))
let color = baseColor.withAlphaComponent(0.5)
let font = baseFont.withSize(12)
let originalString = NSAttributedString(string: baseString, color: color, font: font, alignment: .right)
attributedString.append(originalString)
And the results is the following:
Everything is left aligned. Why? The second part should be right aligned.
I set two style for attributes and the result is ok, try to set like this:
let style = NSMutableParagraphStyle()
style.alignment = .left
let style2 = NSMutableParagraphStyle()
style2.alignment = .right
let attributedString = NSMutableAttributedString(string: "Collectives™ helps you find trusted answers faster, engage with product experts, and share knowledge around the technologies you use most.", attributes: [.paragraphStyle: style, .foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 14, weight: .bold)])
attributedString.append(NSAttributedString(string: "\nCollectives™ helps you find trusted answers faster, engage with product experts, and share knowledge around the technologies you use most.", attributes: [.paragraphStyle: style2, .foregroundColor: UIColor.gray, .font: UIFont.systemFont(ofSize: 12, weight: .semibold)]))
yourTextContainer.attributedText = attributedString
The result:

textfield placeholder centered and also change color

I want to make my UITextField placeholder to center aligned and also change the placeholderColor.
I have already make text center aligned using this ↓
extension String {
func attributedString(aligment: NSTextAlignment) -> NSAttributedString {
return NSAttributedString(text: self, aligment: aligment)
}
}
extension NSAttributedString {
convenience init(text: String, aligment: NSTextAlignment) {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = aligment
self.init(string: text, attributes: [NSAttributedStringKey.paragraphStyle: paragraphStyle])
}
}
and call above extension method like below
textField.attributedPlaceholder = NSAttributedString(text: text, aligment: .left)
But I am not able to change the color of placeholder. How should I change my placeholder color? Any help is appreciated.
Try using modified extension like below..
extension NSAttributedString
{
convenience init(text: String, aligment: NSTextAlignment, color:UIColor) {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = aligment
self.init(string: text, attributes: [NSAttributedStringKey.paragraphStyle: paragraphStyle, NSAttributedStringKey.foregroundColor:color])
}
}
Usage
textField.attributedPlaceholder = NSAttributedString(text: text, aligment: .left, color:UIColor.red)
Simply try this code
Swift 3.0
myTextField.textAlignment = .center
myTextField.attributedPlaceholder = NSAttributedString(string: "PlaceHolder", attributes: [NSForegroundColorAttributeName: UIColor.green])

Underline covers text in NSAttributedString

I'm trying to create an attributed string but the underline covers my text instead of appearing behind it:
Is there a way to fix this? I'm using the following code:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 10.0
let attributes = [NSForegroundColorAttributeName: UIColor.white,
NSUnderlineStyleAttributeName: NSUnderlineStyle.styleThick.rawValue,
NSUnderlineColorAttributeName: UIColor.red,
NSParagraphStyleAttributeName: paragraphStyle]
let attributedString = NSAttributedString(string: "Story", attributes: attributes)
Thanks!
EDIT:
To give more context:
I'm displaying the attributed string on a UILabel placed in a .xib file:
view.textLabel.attributedText = attributedString
The label has the following font:
System Bold 32.0
I'm running the code on iPhone 6 - iOS 10.3 simulator.
EDIT 2:
I should have mentioned that the label may, at some point, contain more than one line of text. That's why the numberOfLines is set to 0.
EDIT 3:
If anybody encounters this problem -- it seems that there is a lot of difference in how underline is drawn on iOS 9 vs 10 as well as UILabel vs UITextView. I've ended up having to draw the underline myself by subclassing NSLayoutManager.
Yes, there is such problem as you have described. It shows up when you use multiline UILabel, so not only setting numberOfLines to 0, but type more than 1 line in it.
Example
let selectedStringAttributes: [String: Any]
= [NSFontAttributeName: UIFont.boldSystemFont(ofSize: 28),
NSForegroundColorAttributeName: UIColor.green,
NSUnderlineStyleAttributeName: NSUnderlineStyle.styleSingle.rawValue,
NSUnderlineColorAttributeName: UIColor.green]
let label = UILabel(frame: CGRect(x: 100, y: 100, width: 500, height: 100))
label.numberOfLines = 0
label.attributedText = NSAttributedString(string: "String to test underline", attributes: selectedStringAttributes)
And everything will look pretty good.
But if you want to use such text:
label.attributedText = NSAttributedString(string: "String to\ntest underline", attributes: selectedStringAttributes)
or label's width is too short, than:
So the reason for such behaviour is of course bug in NSAttributedString. As it mentioned in radar there is a workaround
You should add this attribute to your NSAttributedString
NSBaselineOffsetAttributeName: 0
And magic will happen.
Instead of using NSAttributedString you can draw border below the label with x space using this.
let space:CGFloat = 10
let border = CALayer()
border.backgroundColor = UIColor.red.cgColor
border.frame = CGRect(x: 0, y: (label?.frame.size.height)! + space, width: (label?.frame.size.width)!, height: 1)
label?.layer.addSublayer(border)
On my machine, showing your attributed string in a black-backgrounded UILabel, it makes a quite nice-looking display:
The red thick underline is nicely separated from the text, and is interrupted to allow the descender of the "y" to pass through it.
NOTE You cannot combine the font of the UILabel (set in Interface Builder) with its attributedText. You must set the entire label's text formatting in the attributedText. So, my code looks like this:
let attributes : [String:Any] = [NSForegroundColorAttributeName: UIColor.white,
NSUnderlineStyleAttributeName: NSUnderlineStyle.styleThick.rawValue,
NSUnderlineColorAttributeName: UIColor.red,
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 32)]
let attributedString = NSAttributedString(string: "Story", attributes: attributes)
lab.backgroundColor = .black
lab.attributedText = attributedString
(You will notice that I removed your stipulation of the paragraph line spacing; there is only one line, so this stipulation adds nothing. However, I get the same result even if I restore it.)
So this is my solution to this issue.
I think it is "cleaner" and easier.
Post me if you dont understand :)
class BottomLineTextField: UITextField {
var bottomBorder = UIView()
override func awakeFromNib() {
super.awakeFromNib()
setBottomBorder()
}
func setBottomBorder() {
self.translatesAutoresizingMaskIntoConstraints = false
bottomBorder = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
hasError = false
bottomBorder.translatesAutoresizingMaskIntoConstraints = false
addSubview(bottomBorder)
bottomBorder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
bottomBorder.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
bottomBorder.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
bottomBorder.heightAnchor.constraint(equalToConstant: 1).isActive = true // Set underline height
}
}

How to change UITextfield placeholder color and fontsize using swift 2.0?

How to change UITextfield placeholder & fontsize in SWIFT 2.0?
#1. set Placeholder textfield color Programmatically
var myMutableStringTitle = NSMutableAttributedString()
let Name = "Enter Title" // PlaceHolderText
myMutableStringTitle = NSMutableAttributedString(string:Name, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 20.0)!]) // Font
myMutableStringTitle.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range:NSRange(location:0,length:Name.characters.count)) // Color
txtTitle.attributedPlaceholder = myMutableStringTitle
OR
txtTitle.attributedPlaceholder = NSAttributedString(string:"Enter Title", attributes: [NSForegroundColorAttributeName: yellowColor])
Note : Name is your placeholder of textField.
PlaceHolder TextFiled :
-------------------------------- OR -------------------------------------
#2. set Placeholder textfield color at runtime attribute
Set textfield placeHolder text Enter Title
Click on identity inspector of textfield property.
User Define Runtime Attributes, add color attributes
Key Path : _placeholderLabel.textColor
Type : Color
value : Your Color or RGB value
PlaceHolder TextFiled :
Updated for Swift 3
If you want to change the UITextField Placeholder color for Swift 3, use the following lines of code:
let yourTextFieldName = UITextField(frame: CGRect(x: 0, y: 0, width: 180, height: 21))
yourTextFieldName.attributedPlaceholder = NSAttributedString(string: "placeholder text", attributes: [NSForegroundColorAttributeName: UIColor.white])
Updated for Swift 5
For swift 5.0 use NSAttributedString.Key.foregroundColor instead of NSForegroundColorAttributeName
So, do it like so
textField.attributedPlaceholder = NSAttributedString(string: "placeholder text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
For swift 4 instead of
NSForegroundColorAttributeName
use
NSAttributedStringKey.foregroundColor
You can try with this sample code
let textFld = UITextField();
textFld.frame = CGRectMake(0,0, 200, 30)
textFld.center = self.view.center;
textFld.attributedPlaceholder = NSAttributedString(string:"Test Data for place holder", attributes:[NSForegroundColorAttributeName: UIColor.blueColor(),NSFontAttributeName :UIFont(name: "Arial", size: 10)!])
self.view.addSubview(textFld)
Placeholder for textfield Objective C
NSString* str = #"Placeholder text...";
NSRange range1 = [str rangeOfString:#"Placeholder text..."];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:str];
[attributedText setAttributes:#{
NSFontAttributeName:[UIFont fontWithName:customFont_NotoSans_Regular size:13.0]
}
range:range1];
[attributedText addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:range1];
txtFld.font = [UIFont fontWithName:customFont_NotoSans_Regular size:13.0];
txtFld.keyboardType = UIKeyboardTypeDefault;
txtFld.attributedPlaceholder = attributedText;
It's easy to do with a subclass of UITextField.
Add placeholderColor property to easily set the color, and then observer changing of .placeholder to apply the color to it (with use of .attributedPlaceholder property)
var placeholderColor: UIColor = .lightGray
override var placeholder: String? {
didSet {
let attributes = [ NSAttributedString.Key.foregroundColor: placeholderColor ]
attributedPlaceholder = NSAttributedString(string: placeholder ?? "", attributes: attributes)
}
}
You do need to set the placeholder text programatically for the color to apply.
set Textfield placeholder
let leftBarButtonItem = UIBarButtonItem.init(image: UIImage(named:"ic_nav-bar_back.png"), landscapeImagePhone: nil, style: .plain, target: viewController, action: #selector(viewController.buttonClick(_:)))
leftBarButtonItem.imageInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
leftBarButtonItem.tintColor = UIColor(hex: 0xED6E19)
viewController.navigationItem.setLeftBarButton(leftBarButtonItem, animated: true)
A simple solution is override placeholder property in an UITextField extension. It will update color of placeholder whole project. You don't need to update your code in many places.
extension UITextField {
var placeholder: String? {
get {
attributedPlaceholder?.string
}
set {
guard let newValue = newValue else {
attributedPlaceholder = nil
return
}
let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: Color.textFieldPlaceholder.color]
let attributedText = NSAttributedString(string: newValue, attributes: attributes)
attributedPlaceholder = attributedText
}
}
}
open your identity inspector by selecting text field and then put " placeholderLabel.textColor " in key path by pressing + button .
Give the type " Color " and in value select desired RGB color.
Swift 5
textfiled.attributedPlaceholder = NSAttributedString(string:NSLocalizedString("Input Group Name", comment: "Input Group Name"), attributes: [NSAttributedString.Key.foregroundColor: yourColor.withAlphaComponent(0.5)])

NSTextAttachment image alignment

I am following this cool tutorial Implementing Rich Text with Images on OS X and iOS by #Duncan Groenewald and was able to display images in my UITextView. However, these images are not centered they way I would like them to be. See image
As you can see, I would like my image to be centered on the X-axis.
I tried returning the rect with appropriate values in -attachmentBoundsForTextContainer:proposedLineFragment:glyphPosition:characterIndex but that did not help.
I also tried setting the NSKernAttributeName for the NSTextAttachment attributed string. But all it did was hide the image some how.
Try setting the paragraph style on your attachment with a center alignment.
If your images are embedded in an attributed string as attachments, you can access them by enumerating through the attributed string's attachment attributes.
For example:
attributedContent.enumerateAttribute(NSAttachmentAttributeName, inRange: NSRange(location: 0, length: attributedContent.length), options: nil) { (attribute, range, stop) -> Void in
if let attachment = attribute as? NSTextAttachment {
// this example assumes you want to center all attachments. You can provide additional logic here. For example, check for attachment.image.
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .Center
attributedContent.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
}
}
This is Swift 3.1 using extension:
extension NSMutableAttributedString {
func setAttachmentsAlignment(_ alignment: NSTextAlignment) {
self.enumerateAttribute(NSAttachmentAttributeName, in: NSRange(location: 0, length: self.length), options: .longestEffectiveRangeNotRequired) { (attribute, range, stop) -> Void in
if attribute is NSTextAttachment {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = alignment
self.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
}
}
}
}
In this way you can you easily apply alignment for attachments on attributed string:
let attributeString = NSMutableAttributedString(string: "")
// add attachments
attributeString.setAttachmentsAlignment(.center)
Here's another way how to set the alignment for an NSTextAttachment image. Hopefully this will also help someone struggling with this. I'm using the code below in a func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
var buttonText = "My Button";
let align = NSMutableParagraphStyle();
align.alignment = NSTextAlignment.center;
align.firstLineHeadIndent = 10.0;
align.headIndent = 10.0;
align.tailIndent = -10.0;
let para = NSMutableAttributedString();
// top padding
para.append(NSAttributedString(string: "\n", attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 10.0)!, NSForegroundColorAttributeName: UIColor.white]));
// image
let img = NSTextAttachment();
img.image = UIImage(named: "MyIcon");
img.bounds = CGRect(x: 0, y: UIFont(name: "Helvetica", size: 18.0)!.descender, width: img.image!.size.width, height: img.image!.size.height);
let nas = NSAttributedString(attachment: img).mutableCopy() as! NSMutableAttributedString;
nas.addAttribute(NSParagraphStyleAttributeName, value: align, range: NSRange(location: 0, length: nas.length));
para.append(nas);
// space to text
buttonText = " " + buttonText;
// text
para.append(NSAttributedString(
string: buttonText,
attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 18.0)!, NSForegroundColorAttributeName: UIColor.black]));
// bottom padding
para.append(NSAttributedString(string: "\n", attributes: [NSParagraphStyleAttributeName: align, NSFontAttributeName: UIFont(name: "Helvetica", size: 10.0)!, NSForegroundColorAttributeName: UIColor.white]));
// set cell label
let label = cell.textLabel!;
label.numberOfLines = 0;
label.layer.borderWidth = 0;
label.layer.masksToBounds = false;
label.backgroundColor = UIColor.clear;
label.layer.backgroundColor = UIColor.green;
label.attributedText = para;

Resources