在NSString或nsmutablestring中不可能有多种颜色。我听说过一点NSAttributedString,它是在iPad SDK 3.2(或大约3.2)中引入的,并且在iPhone SDK 4.0 beta版中可用。

我想要一根有三种颜色的绳子。

我不使用3个独立的NSString的原因,是因为三个NSAttributedString子字符串的长度经常改变,所以我宁愿,不使用任何计算重新定位3个独立的NSString对象。

如果使用NSAttributedString是可能的,我怎么做以下-(如果不可能使用NSAttributedString,你会怎么做):

编辑: 记住,@"first", @"second"和@"third"随时会被其他字符串替换。所以使用硬编码的NSRange值是行不通的。


当前回答

自iOS 7以来,你可以使用NSAttributedString与HTML语法:

NSURL *htmlString = [[NSBundle mainBundle]  URLForResource: @"string"     withExtension:@"html"];
NSAttributedString *stringWithHTMLAttributes = [[NSAttributedString alloc] initWithFileURL:htmlString
                                                                                       options:@{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType}
                                                                            documentAttributes:nil
                                                                                         error:nil];
textView.attributedText = stringWithHTMLAttributes;// you can use a label also

你必须添加文件"string.html"到你的项目中,html的内容可以是这样的:

<html>
  <head>
    <style type="text/css">
      body {
        font-size: 15px;
        font-family: Avenir, Arial, sans-serif;
      }
      .red {
        color: red;
      }
      .green {
        color: green;
      }
      .blue {
        color: blue;
      }
    </style>
  </head>
  <body>
    <span class="red">first</span><span class="green">second</span><span class="blue">third</span>
  </body>
</html>  

现在,你可以使用NSAttributedString作为你想要的,即使没有HTML文件,例如:

//At the top of your .m file
#define RED_OCCURENCE -red_occurence-
#define GREEN_OCCURENCE -green_occurence-
#define BLUE_OCCURENCE -blue_occurence-
#define HTML_TEMPLATE @"<span style=\"color:red\">-red_occurence-</span><span style=\"color:green\">-green_occurence-</span><span style=\"color:blue\">-blue_occurence-</span></body></html>"

//Where you need to use your attributed string
NSString *string = [HTML_TEMPLATE stringByReplacingOccurrencesOfString:RED_OCCURENCE withString:@"first"] ;
string = [string stringByReplacingOccurrencesOfString:GREEN_OCCURENCE   withString:@"second"];
string = [string stringByReplacingOccurrencesOfString:BLUE_OCCURENCE    withString:@"third"];

NSData* cData = [string dataUsingEncoding:NSUTF8StringEncoding];

NSAttributedString *stringWithHTMLAttributes = [[NSAttributedString alloc] initWithData:cData
                                                                                options:@{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType}
                                                                        documentAttributes:nil
                                                                                     error:nil];
textView.attributedText = stringWithHTMLAttributes;

其他回答

我写了helper来方便地添加属性:

- (void)addColor:(UIColor *)color substring:(NSString *)substring;
- (void)addBackgroundColor:(UIColor *)color substring:(NSString *)substring;
- (void)addUnderlineForSubstring:(NSString *)substring;
- (void)addStrikeThrough:(int)thickness substring:(NSString *)substring;
- (void)addShadowColor:(UIColor *)color width:(int)width height:(int)height radius:(int)radius substring:(NSString *)substring;
- (void)addFontWithName:(NSString *)fontName size:(int)fontSize substring:(NSString *)substring;
- (void)addAlignment:(NSTextAlignment)alignment substring:(NSString *)substring;
- (void)addColorToRussianText:(UIColor *)color;
- (void)addStrokeColor:(UIColor *)color thickness:(int)thickness substring:(NSString *)substring;
- (void)addVerticalGlyph:(BOOL)glyph substring:(NSString *)substring;

https://github.com/shmidt/MASAttributes

你也可以通过CocoaPods安装:pod 'MASAttributes', '~> 1.0.0'

问题已经有了答案……但是我想展示如何用NSAttributedString添加阴影和改变字体,这样当人们搜索这个主题时,他们就不用一直找了。

#define FONT_SIZE 20
#define FONT_HELVETICA @"Helvetica-Light"
#define BLACK_SHADOW [UIColor colorWithRed:40.0f/255.0f green:40.0f/255.0f blue:40.0f/255.0f alpha:0.4f]

NSString*myNSString = @"This is my string.\nIt goes to a second line.";                

NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
               paragraphStyle.alignment = NSTextAlignmentCenter;
             paragraphStyle.lineSpacing = FONT_SIZE/2;
                     UIFont * labelFont = [UIFont fontWithName:FONT_HELVETICA size:FONT_SIZE];
                   UIColor * labelColor = [UIColor colorWithWhite:1 alpha:1];
                       NSShadow *shadow = [[NSShadow alloc] init];
                 [shadow setShadowColor : BLACK_SHADOW];
                [shadow setShadowOffset : CGSizeMake (1.0, 1.0)];
            [shadow setShadowBlurRadius : 1];

NSAttributedString *labelText = [[NSAttributedString alloc] initWithString : myNSString
                      attributes : @{
   NSParagraphStyleAttributeName : paragraphStyle,
             NSKernAttributeName : @2.0,
             NSFontAttributeName : labelFont,
  NSForegroundColorAttributeName : labelColor,
           NSShadowAttributeName : shadow }];

这是一个Swift版本…

警告! 这适用于4s。

5s你必须改变所有的Float值为Double值(因为编译器还没有正确工作)

字体选择的Swift枚举:

enum FontValue: Int {
    case FVBold = 1 , FVCondensedBlack, FVMedium, FVHelveticaNeue, FVLight, FVCondensedBold, FVLightItalic, FVUltraLightItalic, FVUltraLight, FVBoldItalic, FVItalic
}

用于enum访问的Swift数组(因为enum不能使用'-'):

func helveticaFont (index:Int) -> (String) {
    let fontArray = [
    "HelveticaNeue-Bold",
    "HelveticaNeue-CondensedBlack",
    "HelveticaNeue-Medium",
    "HelveticaNeue",
    "HelveticaNeue-Light",
    "HelveticaNeue-CondensedBold",
    "HelveticaNeue-LightItalic",
    "HelveticaNeue-UltraLightItalic",
    "HelveticaNeue-UltraLight",
    "HelveticaNeue-BoldItalic",
    "HelveticaNeue-Italic",
    ]
    return fontArray[index]
}

Swift属性文本函数:

func myAttributedText (myString:String, mySize: Float, myFont:FontValue) -> (NSMutableAttributedString) {

    let shadow = NSShadow()
    shadow.shadowColor = UIColor.textShadowColor()
    shadow.shadowOffset = CGSizeMake (1.0, 1.0)
    shadow.shadowBlurRadius = 1

    let paragraphStyle = NSMutableParagraphStyle.alloc()
    paragraphStyle.lineHeightMultiple = 1
    paragraphStyle.lineBreakMode = NSLineBreakMode.ByWordWrapping
    paragraphStyle.alignment = NSTextAlignment.Center

    let labelFont = UIFont(name: helveticaFont(myFont.toRaw()), size: mySize)
    let labelColor = UIColor.whiteColor()

    let myAttributes :Dictionary = [NSParagraphStyleAttributeName : paragraphStyle,
                                              NSKernAttributeName : 3, // (-1,5)
                                              NSFontAttributeName : labelFont,
                                   NSForegroundColorAttributeName : labelColor,
                                            NSShadowAttributeName : shadow]

    let myAttributedString = NSMutableAttributedString (string: myString, attributes:myAttributes)

    // add new color 
    let secondColor = UIColor.blackColor()
    let stringArray = myString.componentsSeparatedByString(" ")
    let firstString: String? = stringArray.first
    let letterCount = countElements(firstString!)
    if firstString {
        myAttributedString.addAttributes([NSForegroundColorAttributeName:secondColor], range:NSMakeRange(0,letterCount))
    }

    return  myAttributedString
}

第一个和最后一个扩展名用于查找字符串数组中的范围:

extension Array {
    var last: T? {
        if self.isEmpty {
            NSLog("array crash error - please fix")
            return self [0]
        } else {
            return self[self.endIndex - 1]
        }
    }
}

extension Array {
    var first: T? {
        if self.isEmpty {
            NSLog("array crash error - please fix")
            return self [0]
        } else {
            return self [0]
        }
    }
}

新的颜色:

extension UIColor {
    class func shadowColor() -> UIColor {
        return UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 0.3)
    }
    class func textShadowColor() -> UIColor {
        return UIColor(red: 50.0/255.0, green: 50.0/255.0, blue: 50.0/255.0, alpha: 0.5)
    }
    class func pastelBlueColor() -> UIColor {
        return UIColor(red: 176.0/255.0, green: 186.0/255.0, blue: 255.0/255.0, alpha: 1)
    }
    class func pastelYellowColor() -> UIColor {
        return UIColor(red: 255.0/255.0, green: 238.0/255.0, blue: 140.0/255.0, alpha: 1)
    }
}

我的宏替换:

enum MyConstants: Float {
    case CornerRadius = 5.0
}

我的按钮制造商w/带属性的文本:

func myButtonMaker (myView:UIView) -> UIButton {

    let myButton = UIButton.buttonWithType(.System) as UIButton
    myButton.backgroundColor = UIColor.pastelBlueColor()
    myButton.showsTouchWhenHighlighted = true;
    let myCGSize:CGSize = CGSizeMake(100.0, 50.0)
    let myFrame = CGRectMake(myView.frame.midX - myCGSize.height,myView.frame.midY - 2 * myCGSize.height,myCGSize.width,myCGSize.height)
    myButton.frame = myFrame
    let myTitle = myAttributedText("Button",20.0,FontValue.FVLight)
    myButton.setAttributedTitle(myTitle, forState:.Normal)

    myButton.layer.cornerRadius = myButton.bounds.size.width / MyConstants.CornerRadius.toRaw()
    myButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
    myButton.tag = 100
    myButton.bringSubviewToFront(myView)
    myButton.layerGradient()

    myView.addSubview(myButton)

    return  myButton
}

我的UIView/UILabel maker w/带属性的文本,阴影和圆角:

func myLabelMaker (myView:UIView) -> UIView {

    let myFrame = CGRectMake(myView.frame.midX / 2 , myView.frame.midY / 2, myView.frame.width/2, myView.frame.height/2)
    let mylabelFrame = CGRectMake(0, 0, myView.frame.width/2, myView.frame.height/2)

    let myBaseView = UIView()
    myBaseView.frame = myFrame
    myBaseView.backgroundColor = UIColor.clearColor()

    let myLabel = UILabel()
    myLabel.backgroundColor=UIColor.pastelYellowColor()
    myLabel.frame = mylabelFrame

    myLabel.attributedText = myAttributedText("This is my String",20.0,FontValue.FVLight)
    myLabel.numberOfLines = 5
    myLabel.tag = 100
    myLabel.layer.cornerRadius = myLabel.bounds.size.width / MyConstants.CornerRadius.toRaw()
    myLabel.clipsToBounds = true
    myLabel.layerborders()

    myBaseView.addSubview(myLabel)

    myBaseView.layerShadow()
    myBaseView.layerGradient()

    myView.addSubview(myBaseView)

    return myLabel
}

通用阴影添加:

func viewshadow<T where T: UIView> (shadowObject: T)
{
    let layer = shadowObject.layer
    let radius = shadowObject.frame.size.width / MyConstants.CornerRadius.toRaw();
    layer.borderColor = UIColor.whiteColor().CGColor
    layer.borderWidth = 0.8
    layer.cornerRadius = radius
    layer.shadowOpacity = 1
    layer.shadowRadius = 3
    layer.shadowOffset = CGSizeMake(2.0,2.0)
    layer.shadowColor = UIColor.shadowColor().CGColor
}

视图样式的视图扩展:

extension UIView {
    func layerborders() {
        let layer = self.layer
        let frame = self.frame
        let myColor = self.backgroundColor
        layer.borderColor = myColor.CGColor
        layer.borderWidth = 10.8
        layer.cornerRadius = layer.borderWidth / MyConstants.CornerRadius.toRaw()
    }

    func layerShadow() {
        let layer = self.layer
        let frame = self.frame
        layer.cornerRadius = layer.borderWidth / MyConstants.CornerRadius.toRaw()
        layer.shadowOpacity = 1
        layer.shadowRadius = 3
        layer.shadowOffset = CGSizeMake(2.0,2.0)
        layer.shadowColor = UIColor.shadowColor().CGColor
    }

    func layerGradient() {
        let layer = CAGradientLayer()
        let size = self.frame.size
        layer.frame.size = size
        layer.frame.origin = CGPointMake(0.0,0.0)
        layer.cornerRadius = layer.bounds.size.width / MyConstants.CornerRadius.toRaw();

        var color0 = CGColorCreateGenericRGB(250.0/255, 250.0/255, 250.0/255, 0.5)
        var color1 = CGColorCreateGenericRGB(200.0/255, 200.0/255, 200.0/255, 0.1)
        var color2 = CGColorCreateGenericRGB(150.0/255, 150.0/255, 150.0/255, 0.1)
        var color3 = CGColorCreateGenericRGB(100.0/255, 100.0/255, 100.0/255, 0.1)
        var color4 = CGColorCreateGenericRGB(50.0/255, 50.0/255, 50.0/255, 0.1)
        var color5 = CGColorCreateGenericRGB(0.0/255, 0.0/255, 0.0/255, 0.1)
        var color6 = CGColorCreateGenericRGB(150.0/255, 150.0/255, 150.0/255, 0.1)

        layer.colors = [color0,color1,color2,color3,color4,color5,color6]
        self.layer.insertSublayer(layer, atIndex: 2)
    }
}

实际视图didload函数:

func buttonPress (sender:UIButton!) {
    NSLog("%@", "ButtonPressed")
}

override func viewDidLoad() {
    super.viewDidLoad()

    let myLabel = myLabelMaker(myView)
    let myButton = myButtonMaker(myView)

    myButton.addTarget(self, action: "buttonPress:", forControlEvents:UIControlEvents.TouchUpInside)

    viewshadow(myButton)
    viewshadow(myLabel)

}

在构建带属性字符串时,我更喜欢使用可变子类,只是为了让事情更简洁。

话虽如此,下面是如何创建一个三色带属性字符串:

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"firstsecondthird"];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];

在浏览器中输入。警告实现者

显然你不会像这样硬编码。也许你可以这样做:

NSDictionary *wordToColorMapping = ....;  //an NSDictionary of NSString => UIColor pairs
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@""];
for (NSString *word in wordToColorMapping) {
  UIColor *color = [wordToColorMapping objectForKey:word];
  NSDictionary *attributes = [NSDictionary dictionaryWithObject:color forKey:NSForegroundColorAttributeName];
  NSAttributedString *subString = [[NSAttributedString alloc] initWithString:word attributes:attributes];
  [string appendAttributedString:subString];
  [subString release];
}

//display string

这个方法非常简单。

let text = "This is a colorful attributed string"
let attributedText = 
NSMutableAttributedString.getAttributedString(fromString: text)
attributedText.apply(color: .red, subString: "This")
//Apply yellow color on range
attributedText.apply(color: .yellow, onRange: NSMakeRange(5, 4))

更多详情请点击这里; https://github.com/iOSTechHub/AttributedString

我总是发现使用带属性的字符串是一个令人难以置信的漫长而乏味的过程。

所以我做了一个Mac应用程序,为你创建所有的代码。

https://itunes.apple.com/us/app/attributed-string-creator/id730928349?mt=12