iPhone - UILabel containing text with multiple fonts at the same time

IphoneObjective CUilabel

Iphone Problem Overview


I am looking for a way to use a UILabel (or something similar) to display something like this:

Tom: Some message.

It is like how it's done in for example the Facebook app to display the "what's on your mind?" messages. Does anyone have any suggestions how to approach this?

Iphone Solutions


Solution 1 - Iphone

There is a way to set different / multiple fonts & other properties on Label using NSMutableAttributedString. Foll is my code:

 UIFont *arialFont = [UIFont fontWithName:@"arial" size:18.0];
 NSDictionary *arialDict = [NSDictionary dictionaryWithObject: arialFont forKey:NSFontAttributeName];    
 NSMutableAttributedString *aAttrString = [[NSMutableAttributedString alloc] initWithString:title attributes: arialDict];

 UIFont *VerdanaFont = [UIFont fontWithName:@"verdana" size:12.0];
 NSDictionary *verdanaDict = [NSDictionary dictionaryWithObject:VerdanaFont forKey:NSFontAttributeName];
 NSMutableAttributedString *vAttrString = [[NSMutableAttributedString alloc]initWithString: newsDate attributes:verdanaDict];    
 [vAttrString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:(NSMakeRange(0, 15))];

 [aAttrString appendAttributedString:vAttrString];


 lblText.attributedText = aAttrString;

Note that lblText is the UILabel, outlet as file owner. One can keep on appending as many NSMutableAttributedString he wants..

Also Note that I've added verdana & arial font in my project & added a plist for the same.

Solution 2 - Iphone

Sorry for late answer. Below code works great for me. I am posting this so that it can be helpful to someone.

    UIFont *font1 = [UIFont fontWithName:kMyriadProSemiBold size:15];
NSDictionary *arialDict = [NSDictionary dictionaryWithObject: font1 forKey:NSFontAttributeName];
NSMutableAttributedString *aAttrString1 = [[NSMutableAttributedString alloc] initWithString:@"My" attributes: arialDict];

UIFont *font2 = [UIFont fontWithName:kMyriadProRegular size:15];
NSDictionary *arialDict2 = [NSDictionary dictionaryWithObject: font2 forKey:NSFontAttributeName];
NSMutableAttributedString *aAttrString2 = [[NSMutableAttributedString alloc] initWithString:@"Profile" attributes: arialDict2];


[aAttrString1 appendAttributedString:aAttrString2];
myProfileLabel.attributedText = aAttrString1;

enter image description here

Please notice that My is semibold and profile is regular. I have used MyRiad font. Thanks

Solution 3 - Iphone

Use two UILabel IBOutlets, each with a different format (font/color/etc), as you desire.. Move the second one over the first based on where the first one's text ends. You can get that via sizeWithFont:forWidth:lineBreakMode:

Alternatively, you can subclass UILabel, and draw the text yourself in drawRect. If you do it this way, just add an instance variable to tell you how much of the string to draw in one format, and draw the rest in another.

Update: Please see @Akshay's response below. As of iOS6 UILabel's can contain NSMutableAttributedString. When I wrote this, this was not available.

Solution 4 - Iphone

Update: If you are iOS 6+, then use UILabel.attributedText -- otherwise....

I created this basic UIView subclass to support similar functionality.

The list of things it doesn't support is longer than what it does, but basically it allows you to manage a single line of UILabels and format each as you want. This lets me interject text with a different color in the middle of the line, for instance, and avoid using the heavy-weight UIWebView.

I create these objects by placing a UIView object in my interface (using Interface Builder) and setting the type of the object in IB to MultipartLabel. Then in the code I call updateNumberOfLabels and the various setText selectors as needed.

//  MultipartLabel.m
//  MultiLabelLabel
//
//  Created by Jason Miller on 10/7/09.
//  Copyright 2009 Jason Miller. All rights reserved.
//

#import "MultipartLabel.h"

@interface MultipartLabel (Private)
- (void)updateLayout;
@end

@implementation MultipartLabel

@synthesize containerView;
@synthesize labels;

-(void)updateNumberOfLabels:(int)numLabels;
{
 [containerView removeFromSuperview];
 self.containerView = nil;
 
 self.containerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)] autorelease];
 [self addSubview:self.containerView];
 self.labels = [NSMutableArray array];
 
 while (numLabels-- > 0) {
  UILabel * label = [[UILabel alloc] initWithFrame:CGRectZero];
  [self.containerView addSubview:label];
  [self.labels addObject:label];
  [label release];
 }
 
 [self updateLayout];
}

-(void)setText:(NSString *)text forLabel:(int)labelNum;
{
 if( [self.labels count] > labelNum && labelNum >= 0 )
 {
  UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
  thisLabel.text = text;
 }
 
 [self updateLayout];
}

-(void)setText:(NSString *)text andFont:(UIFont*)font forLabel:(int)labelNum;
{
 if( [self.labels count] > labelNum && labelNum >= 0 )
 {
  UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
  thisLabel.text = text;
  thisLabel.font = font;
 }
 
 [self updateLayout];
}

-(void)setText:(NSString *)text andColor:(UIColor*)color forLabel:(int)labelNum;
{
 if( [self.labels count] > labelNum && labelNum >= 0 )
 {
  UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
  thisLabel.text = text;
  thisLabel.textColor = color;
 }
 
 [self updateLayout];
}

-(void)setText:(NSString *)text andFont:(UIFont*)font andColor:(UIColor*)color forLabel:(int)labelNum;
{
 if( [self.labels count] > labelNum && labelNum >= 0 )
 {
  UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
  thisLabel.text = text;
  thisLabel.font = font;
  thisLabel.textColor = color;
 }
 
 [self updateLayout];
}

- (void)updateLayout {

 int thisX = 0;
 
 // TODO when it is time to support different sized fonts, need to adjust each y value to line up baselines
 
 for (UILabel * thisLabel in self.labels) {
  CGSize size = [thisLabel.text sizeWithFont:thisLabel.font
         constrainedToSize:CGSizeMake(9999, 9999)
          lineBreakMode:thisLabel.lineBreakMode];
  CGRect thisFrame = CGRectMake( thisX, 0, size.width, size.height );
  thisLabel.frame = thisFrame;
  
  thisX += size.width;
 }
}


- (void)dealloc {
 [labels release];
 labels = nil;

 [containerView release];
 containerView = nil;

    [super dealloc];
}


@end

Solution 5 - Iphone

In swift 2.0 this can be done as follows

//Defining fonts of size and type
let firstfont:UIFont = UIFont(name: "Helvetica Neue", size: 17)!
let boldFont:UIFont = UIFont(name: "HelveticaNeue-Bold", size: 17)!
let thirdFont:UIFont = UIFont(name: "HelveticaNeue-ThinItalic", size: 17)!

//Making dictionaries of fonts that will be passed as an attribute        

let firstDict:NSDictionary = NSDictionary(object: firstfont, forKey:  
NSFontAttributeName)
let boldDict:NSDictionary = NSDictionary(object: boldFont, forKey: 
NSFontAttributeName)
let thirdDict:NSDictionary = NSDictionary(object: thirdFont, forKey: 
NSFontAttributeName)
    
let firstText = "My name is "
let attributedString = NSMutableAttributedString(string: firstText, 
attributes: firstDict as? [String : AnyObject])
    
let boldText  = "Rajan"
let boldString = NSMutableAttributedString(string:boldText, 
attributes:boldDict as? [String : AnyObject])

let finalText = " iOS"
let finalAttributedString =  NSMutableAttributedString(string: 
finalText, attributes: thirdDict as? [String : AnyObject])

attributedString.appendAttributedString(boldString)
attributedString.appendAttributedString(finalAttributedString)
myLabel.attributedText = attributedString

Edit
Swift 3.0

let firstfont:UIFont = UIFont(name: "Helvetica Neue", size: 17)!
let boldFont:UIFont = UIFont(name: "HelveticaNeue-Bold", size: 17)!
let thirdFont:UIFont = UIFont(name: "HelveticaNeue-ThinItalic", size: 17)!
    
//Making dictionaries of fonts that will be passed as an attribute
    
let firstDict:NSDictionary = NSDictionary(object: firstfont, forKey:
        NSFontAttributeName as NSCopying)
let boldDict:NSDictionary = NSDictionary(object: boldFont, forKey:
        NSFontAttributeName as NSCopying)
let thirdDict:NSDictionary = NSDictionary(object: thirdFont, forKey:
        NSFontAttributeName as NSCopying)
    
let firstText = "My name is "
let attributedString = NSMutableAttributedString(string: firstText,
                                                     attributes: firstDict as? [String : AnyObject])
    
let boldText  = "Rajan"
let boldString = NSMutableAttributedString(string:boldText,
                                               attributes:boldDict as? [String : AnyObject])
    
let finalText = " iOS"
let finalAttributedString =  NSMutableAttributedString(string:
        finalText, attributes: thirdDict as? [String : AnyObject])
            
attributedString.append(boldString)
attributedString.append(finalAttributedString)
myLabel.attributedText = attributedString

Edit
Swift 4.0

let firstfont:UIFont = UIFont(name: "Helvetica Neue", size: 17)!
let boldFont:UIFont = UIFont(name: "HelveticaNeue-Bold", size: 17)!
let thirdFont:UIFont = UIFont(name: "HelveticaNeue-ThinItalic", size: 17)!

//Making dictionaries of fonts that will be passed as an attribute

let firstDict:NSDictionary = NSDictionary(object: firstfont, forKey:
	NSAttributedString.Key.font as NSCopying)
let boldDict:NSDictionary = NSDictionary(object: boldFont, forKey:
	NSAttributedString.Key.font as NSCopying)
let thirdDict:NSDictionary = NSDictionary(object: thirdFont, forKey:
	NSAttributedString.Key.font as NSCopying)

let firstText = "My name is "
let attributedString = NSMutableAttributedString(string: firstText,
														 attributes: firstDict as? [NSAttributedString.Key : Any])

let boldText  = "Rajan"
let boldString = NSMutableAttributedString(string:boldText,
												   attributes:boldDict as? [NSAttributedString.Key : Any])

let finalText = " iOS"
let finalAttributedString =  NSMutableAttributedString(string:
	finalText, attributes: thirdDict as? [NSAttributedString.Key : Any])

attributedString.append(boldString)
attributedString.append(finalAttributedString)
myLabel.attributedText = attributedString

This will look like

enter image description here

Solution 6 - Iphone

I updated MultipartLabel suggested by @Jason adding contentMode (text alignment) support.

MultipartLabel.h
#import <Foundation/Foundation.h>

@interface MultipartLabel : UIView {
}

@property (nonatomic,retain) UIView *containerView;
@property (nonatomic,retain) NSMutableArray *labels;
@property (nonatomic) UIViewContentMode contentMode;

- (void)updateNumberOfLabels:(int)numLabels;
- (void)setText:(NSString *)text forLabel:(int)labelNum;
- (void)setText:(NSString *)text andFont:(UIFont*)font forLabel:(int)labelNum;
- (void)setText:(NSString *)text andColor:(UIColor*)color forLabel:(int)labelNum;
- (void)setText:(NSString *)text andFont:(UIFont*)font andColor:(UIColor*)color forLabel:(int)labelNum;

@end
MultipartLabel.m
//  MultipartLabel.m
//  MultipartLabel
//
//  Created by Jason Miller on 10/7/09.
//  Updated by Laurynas Butkus, 2011
//  Copyright 2009 Jason Miller. All rights reserved.
//

#import "MultipartLabel.h"

@interface MultipartLabel (Private)
- (void)updateLayout;
@end

@implementation MultipartLabel

@synthesize containerView;
@synthesize labels;
@synthesize contentMode;

-(void)updateNumberOfLabels:(int)numLabels
{
    [containerView removeFromSuperview];
    self.containerView = nil;
    
    self.containerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)] autorelease];
    [self addSubview:self.containerView];
    self.labels = [NSMutableArray array];
    
    while (numLabels-- > 0) {
        UILabel * label = [[UILabel alloc] initWithFrame:CGRectZero];
        label.backgroundColor = self.backgroundColor;
        [self.containerView addSubview:label];
        [self.labels addObject:label];
        [label release];
    }
    
    [self updateLayout];
}

-(void)setText:(NSString *)text forLabel:(int)labelNum
{
    if( [self.labels count] > labelNum && labelNum >= 0 )
    {
        UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
        thisLabel.text = text;
    }
    
    [self updateLayout];
}

-(void)setText:(NSString *)text andFont:(UIFont*)font forLabel:(int)labelNum
{
    if( [self.labels count] > labelNum && labelNum >= 0 )
    {
        UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
        thisLabel.text = text;
        thisLabel.font = font;
    }
    
    [self updateLayout];
}

-(void)setText:(NSString *)text andColor:(UIColor*)color forLabel:(int)labelNum
{
    if( [self.labels count] > labelNum && labelNum >= 0 )
    {
        UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
        thisLabel.text = text;
        thisLabel.textColor = color;
    }
    
    [self updateLayout];
}

- (void)setText:(NSString *)text andFont:(UIFont*)font andColor:(UIColor*)color forLabel:(int)labelNum
{
    if( [self.labels count] > labelNum && labelNum >= 0 )
    {
        UILabel * thisLabel = [self.labels objectAtIndex:labelNum];
        thisLabel.text = text;
        thisLabel.font = font;
        thisLabel.textColor = color;
    }
    
    [self updateLayout];
}

- (void)updateLayout {
    
    int thisX;
    int thisY;
    int totalWidth = 0;
    int offsetX = 0;
    
    int sizes[[self.labels count]][2];
    int i = 0;
    
    for (UILabel * thisLabel in self.labels) {
        CGSize size = [thisLabel.text sizeWithFont:thisLabel.font constrainedToSize:CGSizeMake(9999, 9999) 
                                     lineBreakMode:thisLabel.lineBreakMode];
        
        sizes[i][0] = size.width;
        sizes[i][1] = size.height;
        totalWidth+= size.width;
        
        i++;
    }
    
    i = 0;
    
    for (UILabel * thisLabel in self.labels) {
        // X
        switch (self.contentMode) {
            case UIViewContentModeRight:
            case UIViewContentModeBottomRight:
            case UIViewContentModeTopRight:
                thisX = self.frame.size.width - totalWidth + offsetX;
                break;
                
            case UIViewContentModeCenter:
                thisX = (self.frame.size.width - totalWidth) / 2 + offsetX;
                break;
                
            default:
                thisX = offsetX;
                break;
        }
        
        // Y
        switch (self.contentMode) {
            case UIViewContentModeBottom:
            case UIViewContentModeBottomLeft:
            case UIViewContentModeBottomRight:
                thisY = self.frame.size.height - sizes[i][1];
                break;
                
            case UIViewContentModeCenter:
                thisY = (self.frame.size.height - sizes[i][1]) / 2;
                break;
                
            default:
                thisY = 0;
                break;
        }
        
        thisLabel.frame = CGRectMake( thisX, thisY, sizes[i][0], sizes[i][1] );
        
        offsetX += sizes[i][0];
        
        i++;
    }
}
    
- (void)dealloc {
    [labels release];
    labels = nil;
    
    [containerView release];
    containerView = nil;
    
    [super dealloc];
}
    
@end

Solution 7 - Iphone

Use CoreText API it will be much faster.

Here are few examples

Basically the things you will have to do are: 1: Create UIView subclass 2: In the drawRect: method add the text drawing logic.

The text drawing logic:

  • You will need to know the range of the "name" so if Tom: Some message. is your string you will have to apply different font for range (0, 3).

You can customize everything with CoreText :)

Solution 8 - Iphone

Hi OHAttributelabel is good way for this.You can refer sample code with below link https://github.com/AliSoftware/OHAttributedLabel Import OHAttribute framwork from it and you can set your label as below

 OHAttributedLabel *lblText;
 lblText = [[OHAttributedLabel alloc] initWithFrame:CGRectMake(10,10,100,19)];
 lblText.backgroundColor = [UIColor clearColor];
    lblText.textAlignment = UITextAlignmentCenter;
    lblText.font = [UIFont fontWithName:@"BoschSans-Regular" size:10];
    NSString *strText=@"Tom: Some message.";
    NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString: strText];
    NSRange rangeOfSubstring = [strVersion rangeOfString:@“Tom:];
    if (rangeOfSubstring.location != NSNotFound) {
        [attrStr setFontName:@"BoschSans-BOLD" size:10.0 range:rangeOfSubstring];
    }
    else {
    }
    
    lblText.attributedText = attrStr;
    [self.View addSubview: lblText];
    

Solution 9 - Iphone

One option would be to use a UIWebView instead of UILabel.

An example: http://iphoneincubator.com/blog/windows-views/display-rich-text-using-a-uiwebview

Solution 10 - Iphone

it's quite easy to build you own HTML code =>

UIWebView *titleAd = [UIWebView alloc] init...;

NSString *cssString = [NSString stringWithFormat:@".title {font-family: HelveticaNeue; text-decoration: bold; font-size: %fpt; color: #4083a9;} .author {font-family: HelveticaNeue; text-decoration: bold; font-size: %fpt; color: #3e4545;}",__FONTSIZE_29__, __FONTSIZE_21__];
        
NSString *htmlString = [NSString stringWithFormat:@"<html> <head>     <style type=\"text/css\"> %@ </style> </head> <body>     <p>     <span class=\"title\"> %@ </span>     <span class=\"author\"> proposé par %@ </span>     </p> </body> </html>", cssString, [table title], [table nameOwner]];  
        
[titleAd loadHTMLString:htmlString baseURL:nil]; 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTom van ZummerenView Question on Stackoverflow
Solution 1 - IphoneAkshayView Answer on Stackoverflow
Solution 2 - IphoneAbdul YasinView Answer on Stackoverflow
Solution 3 - IphonemahboudzView Answer on Stackoverflow
Solution 4 - IphoneJasonView Answer on Stackoverflow
Solution 5 - IphoneRajan MaheshwariView Answer on Stackoverflow
Solution 6 - IphoneLaurynasView Answer on Stackoverflow
Solution 7 - IphoneGeorge PetrovView Answer on Stackoverflow
Solution 8 - Iphonesinh99View Answer on Stackoverflow
Solution 9 - IphonegregView Answer on Stackoverflow
Solution 10 - IphoneNielsou Hacken-BergenView Answer on Stackoverflow