How do you use NSAttributedString?

后端 未结 15 936
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 04:19

Multiple colours in an NSString or NSMutableStrings are not possible. So I\'ve heard a little about the NSAttributedString which was introduced wit

相关标签:
15条回答
  • 2020-11-22 05:09

    When building attributed strings, I prefer to use the mutable subclass, just to keep things cleaner.

    That being said, here's how you create a tri-color attributed string:

    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)];
    

    typed in a browser. caveat implementor

    Obviously you're not going to hard-code in the ranges like this. Perhaps instead you could do something like:

    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
    
    0 讨论(0)
  • 2020-11-22 05:10

    The question is already answered... but I wanted to show how to add shadow and change the font with NSAttributedString as well, so that when people search for this topic they won't have to keep looking.

    #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 }];
    

    Here is a Swift version...

    Warning! This works for 4s.

    For 5s you have to change all of the the Float values to Double values (because the compiler isn't working correctly yet)

    Swift enum for font choice:

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

    Swift array for enum access (needed because enum can't use '-'):

    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 attributed text function:

    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
    }
    

    first and last extension used for finding ranges in a string array:

    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]
            }
        }
    }
    

    new colors:

    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)
        }
    }
    

    my macro replacement:

    enum MyConstants: Float {
        case CornerRadius = 5.0
    }
    

    my button maker w/attributed text:

    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
    }
    

    my UIView/UILabel maker w/attributed text, shadow, and round corners:

    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
    }
    

    generic shadow add:

    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
    }
    

    view extension for view style:

    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)
        }
    }
    

    the actual view did load function:

    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)
    
    }
    
    0 讨论(0)
  • 2020-11-22 05:12

    In Swift 4:

    let string:NSMutableAttributedString = {
    
        let mutableString = NSMutableAttributedString(string: "firstsecondthird")
    
        mutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.red , range: NSRange(location: 0, length: 5))
        mutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.green , range: NSRange(location: 5, length: 6))
        mutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blue , range: NSRange(location: 11, length: 5))
        return mutableString
    }()
    
    print(string)
    
    0 讨论(0)
提交回复
热议问题