9

i have UILabel (cocoa touch framework) and i want to right and left justify its text. as a consequence it will stretch the text inside.

Example: like if i had this text "While the saved costs of physical manufacturing and shipping" it would appear like the following:

"While the saved"
"c o s t s   o f"
"p h y s i c a l"
 "manufacturing"
"a n d  shipping"

as you can see left and right justification...

how can i achieve that ???

many thanks

  • i'm sorry i had to put the double qoutations to post the question.
Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
M.Saleh
  • 133
  • 2
  • 2
  • 9
  • try this...youLable.textAlignment = UITextAlignmentLeft. if you have already done that then post code you wrote to set text on label. – Mohammad Sep 11 '11 at 13:21
  • it didn't work. UITextAlignmentRight and UITextAlignmentCenter didn't work either. – M.Saleh Sep 11 '11 at 13:23

8 Answers8

9

You should use my OHAttributedLabel class.

It has everything needed to display an NSAttributedString, including justifying left, center, right… and justified, and is really simple to use.

You can find it here on github. See the sample code provided that also shows how to change text justification.

// suppose that label is an IBOutlet to an OHAttributedLabel (subclass oh UILabel)
label.textAlignment = UITextAlignmentJustify; // and that's all, OHAttributedLabel does everything needed for you!

(Note: UITextAlignmentJustify is a constant defined in OHAttributedLabel headers that matches corresponding CoreText constant for justify alignment. This constant does not exists in Apple's SDK)


[EDIT] iOS6 SDK

Since iOS6 SDK, the UITextAlignmentJustify does not work anymore and generate a crash at runtime. Now you should set the text alignment of your NSAttributedString itself instead of using the textAlignment property of the label.

AliSoftware
  • 32,623
  • 6
  • 82
  • 77
  • does it work with IBOutlets only? i cannot use it with a label created in code? – Andrey Chernukha Jul 21 '12 at 07:07
  • 1
    o_O Errr of course you can ! There is no difference between a label created by IB (and connected to a variable using an IBOutlet) or created by code – AliSoftware Jul 21 '12 at 15:26
  • Very great class, thank you!! But just a little problem I've noticed with this class, sizeToFit didn't work using attributedText. – Luis Ascorbe Oct 29 '12 at 11:57
  • Thx ;) `sizeThatFits:` (and thus `sizeToFit`) should work provided you provided all the attributes of your `NSAttributedString` for all ranges. Are you sure you did set the text and fond of your `NSAttributedString` before applying it to the label? And what version/tag are you using? If it still persists, please search for an existing issu on my repo or create one with some example code if non exist. – AliSoftware Oct 29 '12 at 12:41
  • @AliSoftware i still get stretched and wierd text when i justify using OHAttributedLabel. I am using attributed string to achieve this. – Burhanuddin Sunelwala Apr 29 '13 at 12:42
  • @BurhanuddinSunelwala Just tried right now on the example project provided on my github and can't see anything weird. Please file an issue on my github with some code to reproduce the issue and a screen capture of what you have and what you expect. – AliSoftware Apr 29 '13 at 13:56
  • there are spacing between characters too... anyways my friend found using UILabel itself! I am removing OHAttributedLabel from my project now! – Burhanuddin Sunelwala Apr 29 '13 at 14:03
  • @BurhanuddinSunelwala I don't understand your problem. This IS the definition of the justified alignment, according to CoreText. And this is the same behavior as with UILabel. – AliSoftware Apr 29 '13 at 14:30
  • Yes you are right! but i can achieve the same thing using UILabel itself. – Burhanuddin Sunelwala Apr 29 '13 at 14:45
  • NSTextAlignmentLeft instead of UITextAlignemtnLeft seems to work and is not deprecated – powerj1984 May 03 '13 at 14:51
  • For iOS6+ I would recommend to drop OHAttributedLabel in favour of native `UILabel` with `NSAttributedString`. – Cœur Aug 03 '15 at 04:06
  • Totally agree with @Cœur (that's why `OHAttributedLabel` is deprecated since some time now, BTW). For those interested, I extracted all the handy `NSAttributedString` categories in my new [OHAttributedStringAdditions](https://github.com/AliSoftware/OHAttributedStringAdditions) pod now, which helps you manipulate `NS(Mutable)AttributedString` objects more easily (and is compatible with iOS6+ and TextKit). – AliSoftware Aug 03 '15 at 20:38
4

Using UIWebView can be slow, so if that's an issue CoreText is the way to go.

Here's some code that uses core text to display an attributed string on a view. It indents a bit like UILabel. I've left some other paragraph formatting options in to illustrate how you can set other paragraph properties and also set the attributed string to bold. Remember you'll need to add the CoreText framework otherwise you'll get build errors.

This code doesn't full justify the last line. Not sure you can get this for free in CoreText.

the .h file

//
//  SmartLabel.h
//

#import <UIKit/UIKit.h>
#import <CoreText/CoreText.h> // needed for CTFontRef, CTFontCreateWithName

@interface SmartLabel : UIView
{
    NSMutableAttributedString* _pgSmartString;
}

@property (nonatomic, retain) NSMutableAttributedString* smartString;

- (void) setText: (NSString*) string;
- (void) formatString;

@end

And the .m file

//
//  SmartLabel.m
//

#import "SmartLabel.h"

@implementation SmartLabel

@synthesize smartString = _pgSmartString;

- (void)dealloc
{
    [_pgSmartString release];
    [super dealloc];
}

- (id)initWithFrame:(CGRect)frame;
{
    if ((self = [super initWithFrame:frame]))
    {
        [self setBackgroundColor: [UIColor clearColor]];
    }
    return self;
}


- (void)drawRect:(CGRect)rect
{
    CGContextRef graphicsContext = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(graphicsContext, CGAffineTransformIdentity);

    // turns things right way up
    CGContextTranslateCTM(graphicsContext, 0, self.bounds.size.height);
    CGContextScaleCTM(graphicsContext, 1.0, -1.0);

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)[self smartString]);

    CGRect bounds = [self bounds];
    bounds.origin.x = bounds.origin.x + 8;
    bounds.size.width = bounds.size.width - 16;

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, bounds);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [[self smartString] length]), path, NULL);
    CFRelease(path);

    CTFrameDraw(frame, graphicsContext); 
    CFRelease(frame);
    CFRelease(framesetter);
}


- (void) setText: (NSString*) string;
{
    NSMutableAttributedString* attributedString = [[NSMutableAttributedString alloc] initWithString:string];
    [self setSmartString:attributedString];
    [attributedString release];
    [self formatString];
}


- (void) formatString;
{
    CTTextAlignment alignment = kCTJustifiedTextAlignment; // could put different alignments here

    CGFloat paragraphSpacing = 11.0;
    CGFloat paragraphSpacingBefore = 0.0;
    CGFloat firstLineHeadIndent = 0.0;
    CGFloat headIndent = 0.0;

    CTParagraphStyleSetting altSettings[] = 
    {
        { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment},
        { kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &firstLineHeadIndent},
        { kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), &headIndent},
        { kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &paragraphSpacing},
        { kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &paragraphSpacingBefore},
    }; 

    CTParagraphStyleRef style;
    style = CTParagraphStyleCreate( altSettings, sizeof(altSettings) / sizeof(CTParagraphStyleSetting) );

    if ( style == NULL )
    {
        NSLog(@"***  WARNING *** Unable To Create CTParagraphStyle in apply paragraph formatting" );
        return;
    }

    [[self smartString] addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)style,(NSString*) kCTParagraphStyleAttributeName, nil] range:NSMakeRange(0,[[self smartString] length])];

    CFRelease(style);

    UIFont* boldFont = [UIFont boldSystemFontOfSize:12.0];

    CTFontRef boldCoreTextFontReference =  CTFontCreateWithName ((CFStringRef)[boldFont fontName],[boldFont pointSize], NULL);
    [[self smartString] addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)boldCoreTextFontReference,(NSString*) kCTFontAttributeName, nil] range:NSMakeRange(0,[[self smartString] length])];
}

@end

And to put to use, something like this:

SmartLabel* smartLabel = [[SmartLabel alloc] initWithFrame:CGRectMake(20, 120, 90, 140.0)];
[[self window] addSubview:smartLabel];
[smartLabel setText:@"While the saved costs of physical manufacturing and shipping"];
[smartLabel release];
Obliquely
  • 7,002
  • 2
  • 32
  • 51
2

Its very easy after the release of IOS 6. Use this

//build a style for justification

NSMutableParagraphStyle *stringStyle=[[NSMutableParagraphStyle alloc]init];

[stringStyle setAlignment:NSTextAlignmentJustified];

//build a string with the particular paragraph style

NSMutableAttributedString* yourString=[[NSMutableAttributedString alloc]init];

[yourString addAttribute:NSParagraphStyleAttributeName value:stringStyle range:NSMakeRange(0, [yourString length])];

//and here you go

UILabel *yourLabel;

yourlabel.attributedText=yourString;
Lennart
  • 9,657
  • 16
  • 68
  • 84
Nofel Mahmood
  • 898
  • 7
  • 12
  • in ios 6 fine: but not work for ios 7 : ====== NSMutableParagraphStyle *stringStyle=[[NSMutableParagraphStyle alloc]init]; [stringStyle setAlignment:NSTextAlignmentJustified]; NSMutableAttributedString* descString=[[NSMutableAttributedString alloc]initWithString:cell.lblDetailDesc.text]; [descString addAttribute:NSParagraphStyleAttributeName value:stringStyle range:NSMakeRange(0, [descString length])]; cell.lblDetailDesc.attributedText=descString; – Ram S Jul 24 '14 at 07:44
2

From iOS 6 you can use NSMutableAttributedString for this,

NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithData:[@"Your String value" dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
NSRange rangeOfTitle = NSMakeRange(0,[attrStr length]);
[attrStr addAttribute: NSFontAttributeName value:[UIFont fontWithName:@"Calibri" size:19.0]range:rangeOfTitle];
 myLabel.attributedText = attrStr;
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setLineSpacing:10]; 
style.lineBreakMode = NSLineBreakByWordWrapping;
style.alignment = NSTextAlignmentJustified;
[attrStr addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, myLabel.text.length)];
myLabel.attributedText = attrStr;
Programming Learner
  • 4,351
  • 3
  • 22
  • 34
2

The perfect solution is to used NSMutableParagraphStyle

NSMutableParagraphStyle *paragraphStyles = [[NSMutableParagraphStyle alloc] init];
        paragraphStyles.alignment = NSTextAlignmentJustified;      //justified text
        paragraphStyles.firstLineHeadIndent = 1.0;
        NSDictionary *attributes = @{NSParagraphStyleAttributeName: paragraphStyles};
        NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString: YourString attributes: attributes];
        YourLabel.attributedText = attributedString;
Ahmed Abdallah
  • 2,338
  • 1
  • 19
  • 30
1

This is so called "full justification", but isn't supported by the UILabel system (which only has "alignments" - left, right and centre). If you want this, you'll have to code it up yourself, building a control with CoreText or similar.

Adam Wright
  • 48,938
  • 12
  • 131
  • 152
0

Agree that this can only be done with a good bit of custom coding; which I would think will be some pretty heavy stuff. Before you get into that; and this is depending on your requirement; do consider having a UIWebView where I imagine you would be able to manage text styles and alignments with a bit more freedom using some HTML and CSS coding.

Madhu
  • 2,429
  • 16
  • 31
  • actaully i was using UIWebView and decided to make it as UILabel because of UIWebView heavy loading. – M.Saleh Sep 11 '11 at 13:39
-2

The following works as a quick fix, but note that for anything more than black plain text you'll need some styling or css.

(From: Justified Alignment in UITextView - iPhone)

I have come to a solution that works. First of all, you will need to change your UITextView and use a UIWebView instead.

    Details.h

    @interface Details : UIViewController {
    IBOutlet UIWebView *descripcion;
    }

    @property (nonatomic, retain) UITextView *descripcion;

Then, load your UIWebView as follows:

    Details.m

    [descripcion loadHTMLString:[NSString stringWithFormat:@"<div align='justify'>%@<div>",YOUR_TEXT] baseURL:nil];
Community
  • 1
  • 1
Daniel G. Wilson
  • 14,955
  • 2
  • 32
  • 39