How to make subscripts and superscripts using NSAttributedString?

送分小仙女□ 提交于 2019-11-26 20:09:15

This is possible to do with NSAttributedString. The attribute constant you're looking for depends on your platform. For Mac OS X it is NSSuperscriptAttributeName and on iOS it is kCTSuperscriptAttributeName. Pass in a negative value for subscript.

The only caveat is that UILabel on iOS can't draw NSAttributedStrings (yet, fingers crossed for iOS 6). You would need to draw the text using Core Text or find some third party replacement for UILabel that can draw an NSAttributedString.

Robert Wasmann

Here's what I did in iOS 6. First add the CoreText, and QuartzCore frameworks. Then import:

#import <QuartzCore/QuartzCore.h>
#import <CoreText/CTStringAttributes.h>
#import <CoreText/CoreText.h>

I made a small function that inputs a plain NSString and exports a NSMutableAttributedString with the last character in superscript. This can be modified to allow setting superscript or subscript, change kCTSuperscriptAttributeName value to -1. Also you could add a variable to specify where to put the superscript in the string. Right now it just assumes the end of the string.

- (NSMutableAttributedString *)plainStringToAttributedUnits:(NSString *)string;
{
    NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:string];
    UIFont *font = [UIFont systemFontOfSize:10.0f];
    UIFont *smallFont = [UIFont systemFontOfSize:9.0f];

    [attString beginEditing];
    [attString addAttribute:NSFontAttributeName value:(font) range:NSMakeRange(0, string.length - 2)];
    [attString addAttribute:NSFontAttributeName value:(smallFont) range:NSMakeRange(string.length - 1, 1)];
    [attString addAttribute:(NSString*)kCTSuperscriptAttributeName value:@"1" range:NSMakeRange(string.length - 1, 1)];
    [attString addAttribute:(NSString*)kCTForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, string.length - 1)];
    [attString endEditing];
    return attString;
}

Now when I want to use it I can do the following to put it in a UITextField:

    NSString *qlwUnitsPlainText = @"m3";
    self.quantityLoadWeightUnits_textField.attributedText = [self plainStringToAttributedUnits:qlwUnitsPlainText];

I hope this helps somebody else, there's not many examples out there!

On iOS, I had missed the kCTSuperscriptAttributeName constant but had good results with font size and "baseline". It gives you a little more control too for less obedient fonts:

+ (NSAttributedString *)attributedStringForText:(NSString *)normalText andSuperscript:(NSString *)superscriptText textSize:(CGFloat)textSize
{
    UIFont *normalFont = [Styles mainFontWithSize:textSize];
    UIFont *superFont = [Styles mainFontWithSize:textSize / 2];

    NSMutableAttributedString *finalStr = [[NSMutableAttributedString alloc] initWithString:normalText attributes:@{NSFontAttributeName: normalFont}];

    NSAttributedString *superStr = [[NSAttributedString alloc] initWithString:superscriptText attributes:@{NSFontAttributeName: superFont, NSBaselineOffsetAttributeName:@(textSize/2)}];

    [finalStr appendAttributedString:superStr];

    return finalStr;
}       
kevinl

you can also do the following if you want to make it a litle cleaner

NSDictionary *attr = @{ NSFontAttributeName: smallfont, 
                        (NSString*)kCTSuperscriptAttributeName: @1 }

NSRange fabricWeightRange = NSMakeRange(fabricWeight.location + 2, 1);                   
[subKeyString setAttributes:attr range:fabricWeightRange];

For SubScript use value for kCTSuperscriptAttributeName as @-1.

As per the document

@discussion Value must be a CFNumberRef. Default is int value 0. If supported by the specified font, a value of 1 enables superscripting and a value of -1 enables subscripting.

extern const CFStringRef kCTSuperscriptAttributeName CT_AVAILABLE(10_5, 3_2);

 Example- [lblHeader setText:@“Headers [Alpha1 – text”];

        NSMutableAttributedString *headerSubscript = [[NSMutableAttributedString alloc]initWithAttributedString: lblHeader.attributedText];

        [headerSubscript addAttribute:(NSString *)kCTSuperscriptAttributeName value:@-1 range:NSMakeRange(14,1)];      

        [lblHeader setAttributedText:headerSubscript];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!