193

I need to embed small icons ( sort of custom bullets ) to my UILabel in iOS7. How can I do this in interface designer? Or at least in code?

In Android there are leftDrawable and rightDrawable for labels, but how it is done in iOS? Sample in android :

android sample

2
  • I not familier with Android can you post some image for reference? Commented Oct 11, 2013 at 12:54
  • 2
    create a small imageview and add it as subview to label's object Commented Oct 11, 2013 at 12:58

21 Answers 21

316

You can do this with iOS 7's text attachments, which are part of TextKit. Some sample code:

NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; attachment.image = [UIImage imageNamed:@"MyIcon.png"]; NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment]; NSMutableAttributedString *myString= [[NSMutableAttributedString alloc] initWithString:@"My label text"]; [myString appendAttributedString:attachmentString]; myLabel.attributedText = myString; 
Sign up to request clarification or add additional context in comments.

12 Comments

How about iOS6? Do you have any suggestion?? Thx
@StevenJiang: You'll have to just add a UIImageView to your label
Unfortunately this places the icon after the text. Any chance that we can move this before the text because I can't find a way?!
@reVerse Instead of appending the image (attachment string) to your textual string, you could try that the other way around, so appending the textual string to the attachment string.
Already tried this yesterday. Seems like a missed something because now it works. Thanks. Just in case for everyone who's trying to accomplish the same (since it's slightly different): NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:attachment]; NSMutableAttributedString *myString = [[NSMutableAttributedString alloc] initWithAttributedString:attachmentString]; NSAttributedString *myText = [[NSMutableAttributedString alloc] initWithString:text]; [myString appendAttributedString:myText];
|
218

Here is the way to embed icon in UILabel.

Also to Align the Icon use attachment.bounds


Swift 5.1

// Create Attachment let imageAttachment = NSTextAttachment() imageAttachment.image = UIImage(named:"iPhoneIcon") // Set bound to reposition let imageOffsetY: CGFloat = -5.0 imageAttachment.bounds = CGRect(x: 0, y: imageOffsetY, width: imageAttachment.image!.size.width, height: imageAttachment.image!.size.height) // Create string with attachment let attachmentString = NSAttributedString(attachment: imageAttachment) // Initialize mutable string let completeText = NSMutableAttributedString(string: "") // Add image to mutable string completeText.append(attachmentString) // Add your text to mutable string let textAfterIcon = NSAttributedString(string: "Using attachment.bounds!") completeText.append(textAfterIcon) self.mobileLabel.textAlignment = .center self.mobileLabel.attributedText = completeText 

Objective-C Version

NSTextAttachment *imageAttachment = [[NSTextAttachment alloc] init]; imageAttachment.image = [UIImage imageNamed:@"iPhoneIcon"]; CGFloat imageOffsetY = -5.0; imageAttachment.bounds = CGRectMake(0, imageOffsetY, imageAttachment.image.size.width, imageAttachment.image.size.height); NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:imageAttachment]; NSMutableAttributedString *completeText = [[NSMutableAttributedString alloc] initWithString:@""]; [completeText appendAttributedString:attachmentString]; NSAttributedString *textAfterIcon = [[NSAttributedString alloc] initWithString:@"Using attachment.bounds!"]; [completeText appendAttributedString:textAfterIcon]; self.mobileLabel.textAlignment = NSTextAlignmentRight; self.mobileLabel.attributedText = completeText; 

enter image description here

enter image description here

7 Comments

Vote up for attachment.bounds
Great call on using attachment.bounds. Thats exactly what I was looking for.
In fact, the imageOffsetY can be calculated instead of using a fixed value of -5.0. let imageOffsetY:CGFloat = -(imageAttachment.image!.size.height - self.mobileLabel.font.pointSize) / 2.0;
Note: it slow down compile time
I can do it on storyboard?
|
66

Swift 4.2:

let attachment = NSTextAttachment() attachment.image = UIImage(named: "yourIcon.png") let attachmentString = NSAttributedString(attachment: attachment) let myString = NSMutableAttributedString(string: price) myString.append(attachmentString) label.attributedText = myString 

Comments

25

Swift 3 version

let attachment = NSTextAttachment() attachment.image = UIImage(named: "plus") attachment.bounds = CGRect(x: 0, y: 0, width: 10, height: 10) let attachmentStr = NSAttributedString(attachment: attachment) let myString = NSMutableAttributedString(string: "") myString.append(attachmentStr) let myString1 = NSMutableAttributedString(string: "My label text") myString.append(myString1) lbl.attributedText = myString 

UILabel Extension

extension UILabel { func set(text:String, leftIcon: UIImage? = nil, rightIcon: UIImage? = nil) { let leftAttachment = NSTextAttachment() leftAttachment.image = leftIcon leftAttachment.bounds = CGRect(x: 0, y: -2.5, width: 20, height: 20) if let leftIcon = leftIcon { leftAttachment.bounds = CGRect(x: 0, y: -2.5, width: leftIcon.size.width, height: leftIcon.size.height) } let leftAttachmentStr = NSAttributedString(attachment: leftAttachment) let myString = NSMutableAttributedString(string: "") let rightAttachment = NSTextAttachment() rightAttachment.image = rightIcon rightAttachment.bounds = CGRect(x: 0, y: -5, width: 20, height: 20) let rightAttachmentStr = NSAttributedString(attachment: rightAttachment) if semanticContentAttribute == .forceRightToLeft { if rightIcon != nil { myString.append(rightAttachmentStr) myString.append(NSAttributedString(string: " ")) } myString.append(NSAttributedString(string: text)) if leftIcon != nil { myString.append(NSAttributedString(string: " ")) myString.append(leftAttachmentStr) } } else { if leftIcon != nil { myString.append(leftAttachmentStr) myString.append(NSAttributedString(string: " ")) } myString.append(NSAttributedString(string: text)) if rightIcon != nil { myString.append(NSAttributedString(string: " ")) myString.append(rightAttachmentStr) } } attributedText = myString } } 

Comments

23

Your reference image looks like a button. Try (can also be done in Interface Builder):

enter image description here

UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setFrame:CGRectMake(50, 50, 100, 44)]; [button setImage:[UIImage imageNamed:@"img"] forState:UIControlStateNormal]; [button setImageEdgeInsets:UIEdgeInsetsMake(0, -30, 0, 0)]; [button setTitle:@"Abc" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor yellowColor]]; [view addSubview:button]; 

2 Comments

Well explained, I like the fact you took the time to provide a ref. It helped me a lot! Thanks
This helped get my trophy icon into a button. Thanks a lot!
16

I've made an implementation of this feature in swift here: https://github.com/anatoliyv/SMIconLabel

Code is as simple as it's possible:

var labelLeft = SMIconLabel(frame: CGRectMake(10, 10, view.frame.size.width - 20, 20)) labelLeft.text = "Icon on the left, text on the left" // Here is the magic labelLeft.icon = UIImage(named: "Bell") // Set icon image labelLeft.iconPadding = 5 // Set padding between icon and label labelLeft.numberOfLines = 0 // Required labelLeft.iconPosition = SMIconLabelPosition.Left // Icon position view.addSubview(labelLeft) 

Here is how it looks:

SMIconLabel image

Comments

15

Swift 5 Easy Way Just CopyPaste and change what you want

let fullString = NSMutableAttributedString(string:"To start messaging contacts who have Talklo, tap ") // create our NSTextAttachment let image1Attachment = NSTextAttachment() image1Attachment.image = UIImage(named: "chatEmoji") image1Attachment.bounds = CGRect(x: 0, y: -8, width: 25, height: 25) // wrap the attachment in its own attributed string so we can append it let image1String = NSAttributedString(attachment: image1Attachment) // add the NSTextAttachment wrapper to our full string, then add some more text. fullString.append(image1String) fullString.append(NSAttributedString(string:" at the right bottom of your screen")) // draw the result in a label self.lblsearching.attributedText = fullString 

enter image description here

6 Comments

From 2021, what happened to your screen;)
its my girlFriend Gift, she left me but how can i trash the gift?? :-(
Sad story. I think you should keep it.
never thought stack overflow would give me depression in this way
@ShakeelAhmed I'm from the future, are you okay now? Still single or married?
|
14

Swift 4 UIlabel Extension to add Image to Label with reference to above answers

extension UILabel { func set(image: UIImage, with text: String) { let attachment = NSTextAttachment() attachment.image = image attachment.bounds = CGRect(x: 0, y: 0, width: 10, height: 10) let attachmentStr = NSAttributedString(attachment: attachment) let mutableAttributedString = NSMutableAttributedString() mutableAttributedString.append(attachmentStr) let textString = NSAttributedString(string: text, attributes: [.font: self.font]) mutableAttributedString.append(textString) self.attributedText = mutableAttributedString } } 

3 Comments

NSAttributedString(string: " " + text, attributes: [.font: self.font])
@grizzly is that for creating space between icon and text?
yes. is another way for space between icon and text?
13

In Swift 5, By using UILabel extensions to embed icon in leading as well as trailing side of the text as follows:-

extension UILabel { func addTrailing(image: UIImage, text:String) { let attachment = NSTextAttachment() attachment.image = image let attachmentString = NSAttributedString(attachment: attachment) let string = NSMutableAttributedString(string: text, attributes: [:]) string.append(attachmentString) self.attributedText = string } func addLeading(image: UIImage, text:String) { let attachment = NSTextAttachment() attachment.image = image let attachmentString = NSAttributedString(attachment: attachment) let mutableAttributedString = NSMutableAttributedString() mutableAttributedString.append(attachmentString) let string = NSMutableAttributedString(string: text, attributes: [:]) mutableAttributedString.append(string) self.attributedText = mutableAttributedString } } 

To use above mentioned code in your desired label as:-

Image in right of text then:-

statusLabel.addTrailing(image: UIImage(named: "rightTick") ?? UIImage(), text: " Verified ") 

Image in left of text then:-

statusLabel.addLeading(image: UIImage(named: "rightTick") ?? UIImage(), text: " Verified ") 

Output:-

enter image description here

enter image description here

Comments

5

try this way...

 self.lbl.text=@"Drawble Left"; UIImageView *img=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)]; img.image=[UIImage imageNamed:@"Star.png"]; [self.lbl addSubview:img]; 

2 Comments

Is this helpful to you?
this approach misses text offset for image (text lies behind image)
4

Swift 5+

If you want to keep the ratio of the image and the image always centered with the text, then, this is my solution:

extension UILabel { var mutableAttributedString: NSMutableAttributedString? { let attributedString: NSMutableAttributedString if let labelattributedText = self.attributedText { attributedString = NSMutableAttributedString(attributedString: labelattributedText) } else { guard let labelText = self.text else { return nil } let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = self.textAlignment attributedString = NSMutableAttributedString(string: labelText) attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length)) } return attributedString } func addImage(_ image: UIImage, toEndWith height: CGFloat) { let fullAttributedString = mutableAttributedString let imageAttachment = NSTextAttachment() imageAttachment.image = image let yImage = (font.capHeight - height).rounded() / 2 let ratio = image.size.width / image.size.height imageAttachment.bounds = CGRect(x: 0, y: yImage, width: ratio * height, height: height) let imageString = NSAttributedString(attachment: imageAttachment) fullAttributedString?.append(imageString) attributedText = fullAttributedString } func addImage(_ image: UIImage, toStartWith height: CGFloat) { let imageAttachment = NSTextAttachment() imageAttachment.image = image let yImage = (font.capHeight - height).rounded() / 2 let ratio = image.size.width / image.size.height imageAttachment.bounds = CGRect(x: 0, y: yImage, width: ratio * height, height: height) let fullAttributed = NSMutableAttributedString(attachment: imageAttachment) if let rawAttributed = mutableAttributedString { fullAttributed.append(rawAttributed) } attributedText = fullAttributed } } 

And this is how to use the above extension:

let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20)) label.font = .systemFont(ofSize: 20) let image = UIImage(systemName: "square.and.pencil")! label.text = "Hi, " label.addImage(image, toEndWith: 10) 

These are some examples:

enter image description here

enter image description here

enter image description here

Using with an attributed string:

let myString = "Hi, " let myAttribute: [NSAttributedString.Key: UIColor] = [.foregroundColor: .blue] let myAttrString = NSAttributedString(string: myString, attributes: myAttribute) label.attributedText = myAttrString label.addImage(image, toEndWith: 15) 

enter image description here

Comments

3

Swift 2.0 version:

//Get image and set it's size let image = UIImage(named: "imageNameWithHeart") let newSize = CGSize(width: 10, height: 10) //Resize image UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0) image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height)) let imageResized = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() //Create attachment text with image var attachment = NSTextAttachment() attachment.image = imageResized var attachmentString = NSAttributedString(attachment: attachment) var myString = NSMutableAttributedString(string: "I love swift ") myString.appendAttributedString(attachmentString) myLabel.attributedText = myString 

Comments

2

Try dragging a UIView onto the screen in IB. From there you can drag a UIImageView and UILabel into the view you just created. Set the image of the UIImageView in the properties inspector as the custom bullet image (which you will have to add to your project by dragging it into the navigation pane) and you can write some text in the label.

Comments

2

You can extent UILabe pass the flag for the image add-in Leading or Trailing also set imageBounds if needed.

Swift 5+

extension UILabel { func add(image: UIImage, text: String, isLeading: Bool = true, imageBounds: CGRect = CGRect(x: 0, y: 0, width: 16, height: 12)) { let imageAttachment = NSTextAttachment() imageAttachment.bounds = imageBounds imageAttachment.image = image let attachmentString = NSAttributedString(attachment: imageAttachment) let string = NSMutableAttributedString(string: text) let mutableAttributedString = NSMutableAttributedString() if isLeading { mutableAttributedString.append(attachmentString) mutableAttributedString.append(string) attributedText = mutableAttributedString } else { string.append(attachmentString) attributedText = string } } } 

Comments

2

For somebody who wants to have an icon on the right end of their label, not necessarily immediately after the text, you can use this technique based on the idea in this answer: https://stackoverflow.com/a/19318843/826946 (Note there are some constants here you will probably want to adjust, but the general idea should be clear). This will not work if your label is being sized using its implicit size, only if you have some other constraint on the width that you are confident will leave room for your icon.

 let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20)) imgView.image = UIImage(named: "arrow") myLabel.addSubview(imgView) imgView.translatesAutoresizingMaskIntoConstraints = false imgView.centerYAnchor.constraint(equalTo: myLabel.centerYAnchor, constant: 0).isActive = true imgView.rightAnchor.constraint(equalTo: myLabel.rightAnchor, constant: -20).isActive = true 

Comments

1

you have to make a custom object where you used a UIView and inside you put a UIImageView and a UILabel

Comments

1

You could use a UITextField with the leftView property and then set the enabled property to NO

Or use a UIButton and setImage:forControlState

Comments

1
 func atributedLabel(str: String, img: UIImage)->NSMutableAttributedString { let iconsSize = CGRect(x: 0, y: -2, width: 16, height: 16) let attributedString = NSMutableAttributedString() let attachment = NSTextAttachment() attachment.image = img attachment.bounds = iconsSize attributedString.append(NSAttributedString(attachment: attachment)) attributedString.append(NSAttributedString(string: str)) return attributedString } 

You can use this function to add images or small icons to the label

3 Comments

Call this in viewdidload()
let emojisCollection = [UIImage(named: "ic_place"), UIImage(named: "ic_group"), UIImage(named: "ic_analytics")] lbl1.attributedText = atributedLabel(str: " Howath, Dublin", img: emojisCollection[0]!) lbl2.attributedText = atributedLabel(str: " Difficulty: 18+", img: emojisCollection[2]!) lbl3.attributedText = atributedLabel(str: " Maximum group size: 10", img: emojisCollection[1]!)
you can edit you original answer to include those comments above.
0

In Swift 2.0,

My solution to the problem is a combination of a couple of answers on this question. The problem I faced in @Phil's answer was that I couldn't change the position of the icon, and it always appeared in right the corner. And the one answer from @anatoliy_v, I couldn't resize the icon size I want to append to the string.

To make it work for me, I first did a pod 'SMIconLabel' and then created this function:

func drawTextWithIcon(labelName: SMIconLabel, imageName: String, labelText: String!, width: Int, height: Int) { let newSize = CGSize(width: width, height: height) let image = UIImage(named: imageName) UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0) image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height)) let imageResized = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() labelName.text = " \(labelText)" labelName.icon = imageResized labelName.iconPosition = .Left } 

This solution will not only help you place the image but will also allow you to make necessary changes to the icon size and other attributes.

Thank You.

Comments

0

Swift 3 UILabel extention

Tip: If you need some space between the image and the text just use a space or two before the labelText.

extension UILabel { func addIconToLabel(imageName: String, labelText: String, bounds_x: Double, bounds_y: Double, boundsWidth: Double, boundsHeight: Double) { let attachment = NSTextAttachment() attachment.image = UIImage(named: imageName) attachment.bounds = CGRect(x: bounds_x, y: bounds_y, width: boundsWidth, height: boundsHeight) let attachmentStr = NSAttributedString(attachment: attachment) let string = NSMutableAttributedString(string: "") string.append(attachmentStr) let string2 = NSMutableAttributedString(string: labelText) string.append(string2) self.attributedText = string } } 

1 Comment

I used this and it worked perfectly. The other ones above actually flipped the image to the end of the string.
0

If you don't absolutely need a label (and there may be some situations where you do), you can use a view hierarchy with constraints to create a UIView that can be placed where a label would go. And, of course the image and label text of the composite view can be updated dynamically.

func configureTitleLabelWithIcon(text: String, parent: UIView) { let iconAndLabel = UIView() let label = UILabel() let icon = UIImageView(image:UIImage(systemName: "globe")) label.text = text label.textColor = UIColor.secondaryLabel label.translatesAutoresizingMaskIntoConstraints = false ico .translatesAutoresizingMaskIntoConstraints = false iconAndLabel.translatesAutoresizingMaskIntoConstraints = false iconAndLabel.addSubview(icon) iconAndLabel.addSubview(label) icon.widthAnchor.constraint( equalToConstant: 14).isActive = true icon.heightAnchor.constraint( equalToConstant: 14).isActive = true iconAndLabel.widthAnchor.constraint( equalToConstant: 200).isActive = true iconAndLabel.heightAnchor.constraint( equalToConstant: 22).isActive = true icon.leadingAnchor.constraint(equalTo: iconAndLabel.leadingAnchor).isActive = true icon.trailingAnchor.constraint(equalTo: label.leadingAnchor, constant: -7).isActive = true label.trailingAnchor.constraint(equalTo: iconAndLabel.trailingAnchor).isActive = true icon.centerYAnchor.constraint(equalTo: iconAndLabel.centerYAnchor).isActive = true view.addSubview(iconAndLabel) label.centerXAnchor.constraint(equalTo: parent, constant: 10).isActive = true label.bottomAnchor.constraint(equalTo: parent, constant: -75).isActive = true } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.