webentwicklung-frage-antwort-db.com.de

Fett und nicht fett gedruckter Text in einem einzigen UILabel?

Wie wäre es möglich, sowohl fetten als auch nicht fetten Text in ein uiLabel aufzunehmen?

Ich würde lieber kein UIWebView verwenden. Ich habe auch gelesen, dass dies mit NSAttributedString möglich ist, aber ich habe keine Ahnung, wie ich das verwenden soll. Irgendwelche Ideen?

Apple erreicht dies in mehreren seiner Apps. Beispiele Screenshot: link text

Vielen Dank! - Dom

240
DomMaiocchi

Aktualisieren

In Swift müssen wir uns nicht mit alten Sachen aus iOS5 befassen, außer dass die Syntax kürzer ist, damit alles wirklich einfach wird:

Swift 5

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: fontSize),
        NSAttributedString.Key.foregroundColor: UIColor.black
    ]
    let nonBoldAttribute = [
        NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

Swift 3

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSFontAttributeName: UIFont.boldSystemFont(ofSize: fontSize),
        NSForegroundColorAttributeName: UIColor.black
    ]
    let nonBoldAttribute = [
        NSFontAttributeName: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

Verwendung:

let targetString = "Updated 2012/10/14 21:59 PM"
let range = NSMakeRange(7, 12)

let label = UILabel(frame: CGRect(x:0, y:0, width:350, height:44))
label.backgroundColor = UIColor.white
label.attributedText = attributedString(from: targetString, nonBoldRange: range)
label.sizeToFit()

Bonus: Internationalisierung

Einige Leute äußerten sich zur Internationalisierung. Ich persönlich denke, dass dies nicht in den Rahmen dieser Frage fällt, aber zu Unterrichtszwecken würde ich es so machen

// Date we want to show
let date = Date()

// Create the string.
// I don't set the locale because the default locale of the formatter is `NSLocale.current` so it's good for internationalisation :p
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let targetString = String(format: NSLocalizedString("Update %@", comment: "Updated string format"),
                          formatter.string(from: date))

// Find the range of the non-bold part
formatter.timeStyle = .none
let nonBoldRange = targetString.range(of: formatter.string(from: date))

// Convert Range<Int> into NSRange
let nonBoldNSRange: NSRange? = nonBoldRange == nil ?
    nil :
    NSMakeRange(targetString.distance(from: targetString.startIndex, to: nonBoldRange!.lowerBound),
                targetString.distance(from: nonBoldRange!.lowerBound, to: nonBoldRange!.upperBound))

// Now just build the attributed string as before :)
label.attributedText = attributedString(from: targetString,
                                        nonBoldRange: nonBoldNSRange)

Ergebnis (vorausgesetzt, es sind englische und japanische Localizable.strings verfügbar)

enter image description here

enter image description here


Vorherige Antwort für iOS6 und höher (Objective-C funktioniert noch):

Unterstützen Sie in iOS6 UILabel, UIButton, UITextView, UITextField zugewiesene Zeichenfolgen, was bedeutet, dass wir CATextLayers nicht als unsere erstellen müssen Empfänger für zugeschriebene Zeichenfolgen. Um den zugewiesenen String zu erstellen, müssen wir nicht mehr mit CoreText spielen :) Wir haben neue Klassen in obj-c Foundation.framework, wie NSParagraphStyle und andere Konstanten, die unser Leben erleichtern. Yay!

Also, wenn wir diesen String haben:

NSString *text = @"Updated: 2012/10/14 21:59"

Wir müssen nur den zugewiesenen String erstellen:

if ([_label respondsToSelector:@selector(setAttributedText:)])
{
    // iOS6 and above : Use NSAttributedStrings

    // Create the attributes
    const CGFloat fontSize = 13;
    NSDictionary *attrs = @{
        NSFontAttributeName:[UIFont boldSystemFontOfSize:fontSize],
        NSForegroundColorAttributeName:[UIColor whiteColor]
    };
    NSDictionary *subAttrs = @{
        NSFontAttributeName:[UIFont systemFontOfSize:fontSize]
    };

    // Range of " 2012/10/14 " is (8,12). Ideally it shouldn't be hardcoded
    // This example is about attributed strings in one label
    // not about internationalisation, so we keep it simple :)
    // For internationalisation example see above code in Swift
    const NSRange range = NSMakeRange(8,12);

    // Create the attributed string (text + attributes)
    NSMutableAttributedString *attributedText =
      [[NSMutableAttributedString alloc] initWithString:text
                                             attributes:attrs];
    [attributedText setAttributes:subAttrs range:range];

    // Set it in our UILabel and we are done!
    [_label setAttributedText:attributedText];
} else {
    // iOS5 and below
    // Here we have some options too. The first one is to do something
    // less fancy and show it just as plain text without attributes.
    // The second is to use CoreText and get similar results with a bit
    // more of code. Interested people please look down the old answer.

    // Now I am just being lazy so :p
    [_label setText:text];
}

Es gibt ein paar gute einführende Blog-Posts hier von Leuten bei invasivecode , die mit mehr Beispielen Gebrauch erklären von NSAttributedString, suchen Sie nach "Introduction to NSAttributedString for iOS 6" und "Attributed Strings for iOS using Interface Builder" :)

PS: Über dem Code sollte es funktionieren, aber es wurde vom Gehirn kompiliert. Ich hoffe es reicht :)


Alte Antwort für iOS5 und darunter

Verwenden Sie eine CATextLayer mit einem NSAttributedString! viel leichter und einfacher als 2 UILabels. (iOS 3.2 und höher)

Beispiel.

Vergessen Sie nicht, QuartzCore-Framework (für CALayers erforderlich) und CoreText (für den zugeordneten String erforderlich) hinzuzufügen.

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

Das folgende Beispiel fügt der Symbolleiste des Navigationscontrollers eine Unterebene hinzu. à la Mail.app auf dem iPhone. :)

- (void)setRefreshDate:(NSDate *)aDate
{
    [aDate retain];
    [refreshDate release];
    refreshDate = aDate;

    if (refreshDate) {

        /* Create the text for the text layer*/    
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"MM/dd/yyyy hh:mm"];

        NSString *dateString = [df stringFromDate:refreshDate];
        NSString *prefix = NSLocalizedString(@"Updated", nil);
        NSString *text = [NSString stringWithFormat:@"%@: %@",prefix, dateString];
        [df release];

        /* Create the text layer on demand */
        if (!_textLayer) {
            _textLayer = [[CATextLayer alloc] init];
            //_textLayer.font = [UIFont boldSystemFontOfSize:13].fontName; // not needed since `string` property will be an NSAttributedString
            _textLayer.backgroundColor = [UIColor clearColor].CGColor;
            _textLayer.wrapped = NO;
            CALayer *layer = self.navigationController.toolbar.layer; //self is a view controller contained by a navigation controller
            _textLayer.frame = CGRectMake((layer.bounds.size.width-180)/2 + 10, (layer.bounds.size.height-30)/2 + 10, 180, 30);
            _textLayer.contentsScale = [[UIScreen mainScreen] scale]; // looks Nice in retina displays too :)
            _textLayer.alignmentMode = kCAAlignmentCenter;
            [layer addSublayer:_textLayer];
        }

        /* Create the attributes (for the attributed string) */
        CGFloat fontSize = 13;
        UIFont *boldFont = [UIFont boldSystemFontOfSize:fontSize];
        CTFontRef ctBoldFont = CTFontCreateWithName((CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
        UIFont *font = [UIFont systemFontOfSize:13];
        CTFontRef ctFont = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL);
        CGColorRef cgColor = [UIColor whiteColor].CGColor;
        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (id)ctBoldFont, (id)kCTFontAttributeName,
                                    cgColor, (id)kCTForegroundColorAttributeName, nil];
        CFRelease(ctBoldFont);
        NSDictionary *subAttributes = [NSDictionary dictionaryWithObjectsAndKeys:(id)ctFont, (id)kCTFontAttributeName, nil];
        CFRelease(ctFont);

        /* Create the attributed string (text + attributes) */
        NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes];
        [attrStr addAttributes:subAttributes range:NSMakeRange(prefix.length, 12)]; //12 is the length of " MM/dd/yyyy/ "

        /* Set the attributes string in the text layer :) */
        _textLayer.string = attrStr;
        [attrStr release];

        _textLayer.opacity = 1.0;
    } else {
        _textLayer.opacity = 0.0;
        _textLayer.string = nil;
    }
}

In diesem Beispiel habe ich nur zwei verschiedene Schriftarten (fett und normal), aber Sie könnten auch eine andere Schriftgröße, andere Farbe, Kursivschrift, Unterstrichen usw. haben. Schauen Sie sich an. NSAttributedString / NSMutableAttributedString und CoreText-Attribute Zeichenfolgenschlüssel .

Ich hoffe es hilft

350
nacho4d

Probieren Sie eine Kategorie bei UILabel aus:

So wird es benutzt:

myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];

Und hier ist die Kategorie

ILabel + Boldify.h

- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;

ILabel + Boldify.m

- (void) boldRange: (NSRange) range {
    if (![self respondsToSelector:@selector(setAttributedText:)]) {
        return;
    }
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];

    self.attributedText = attributedText;    
}

- (void) boldSubstring: (NSString*) substring {
    NSRange range = [self.text rangeOfString:substring];
    [self boldRange:range];
}

Beachten Sie, dass dies nur in iOS 6 und höher funktioniert. In iOS 5 und früheren Versionen wird es einfach ignoriert.

83
bbrame

Das geht ganz einfach in Interface Builder:

1) make UILabel Attributed in Attributes Inspector

Bold Example Step 1

2) Wählen Sie einen Teil der Phrase aus, die fett gedruckt werden soll

Bold Example Step 2

3) Ändern Sie die Schriftart (oder die Fettschrift derselben Schriftart) in der Schriftartauswahl .

Bold Example Step 3

Das ist alles!

47
Anton Gaenko

Es gibt eine Kategorie, die auf der Kategorie von bbrame basiert. Es funktioniert ähnlich, aber Sie können dasselbe UILabel mehrmals mit kumulativen Ergebnissen fett formatieren.

ILabel + Boldify.h

@interface UILabel (Boldify)
- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;
@end

ILabel + Boldify.m

@implementation UILabel (Boldify)
- (void)boldRange:(NSRange)range {
    if (![self respondsToSelector:@selector(setAttributedText:)]) {
        return;
    }
    NSMutableAttributedString *attributedText;
    if (!self.attributedText) {
        attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
    } else {
        attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    }
    [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];
    self.attributedText = attributedText;
}

- (void)boldSubstring:(NSString*)substring {
    NSRange range = [self.text rangeOfString:substring];
    [self boldRange:range];
}
@end

Mit diesen Korrekturen können Sie es mehrmals verwenden, zB:

myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];

wird ergeben mit: "pdated: 2012/10/14 21:59 PM".

45
Crazy Yoghurt

Es hat bei mir funktioniert:

CGFloat boldTextFontSize = 17.0f;

myLabel.text = [NSString stringWithFormat:@"%@ 2012/10/14 %@",@"Updated:",@"21:59 PM"];

NSRange range1 = [myLabel.text rangeOfString:@"Updated:"];
NSRange range2 = [myLabel.text rangeOfString:@"21:59 PM"];

NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:myLabel.text];

[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
                        range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
                        range:range2];

myLabel.attributedText = attributedText;

Für Swift Version: Siehe hier

26

Ich habe die Antwort von Crazy Yoghurt auf Swifts Erweiterungen übernommen.

extension UILabel {

    func boldRange(_ range: Range<String.Index>) {
        if let text = self.attributedText {
            let attr = NSMutableAttributedString(attributedString: text)
            let start = text.string.characters.distance(from: text.string.startIndex, to: range.lowerBound)
            let length = text.string.characters.distance(from: range.lowerBound, to: range.upperBound)
            attr.addAttributes([NSFontAttributeName: UIFont.boldSystemFont(ofSize: self.font.pointSize)], range: NSMakeRange(start, length))
            self.attributedText = attr
        }
    }

    func boldSubstring(_ substr: String) {
        if let text = self.attributedText {
            var range = text.string.range(of: substr)
            let attr = NSMutableAttributedString(attributedString: text)
            while range != nil {
                let start = text.string.characters.distance(from: text.string.startIndex, to: range!.lowerBound)
                let length = text.string.characters.distance(from: range!.lowerBound, to: range!.upperBound)
                var nsRange = NSMakeRange(start, length)
                let font = attr.attribute(NSFontAttributeName, at: start, effectiveRange: &nsRange) as! UIFont
                if !font.fontDescriptor.symbolicTraits.contains(.traitBold) {
                    break
                }
                range = text.string.range(of: substr, options: NSString.CompareOptions.literal, range: range!.upperBound..<text.string.endIndex, locale: nil)
            }
            if let r = range {
                boldRange(r)
            }
        }
    }
}

Möglicherweise gibt es keine gute Konvertierung zwischen Range und NSRange, aber ich habe nichts Besseres gefunden.

25
Artem Mostyaev

Check out TTTAttributedLabel . Es ist ein Drop-In-Ersatz für UILabel, mit dem Sie Schriftarten und Farben in einer einzelnen Beschriftung mischen können, indem Sie einen NSAttributedString als Text für diese Beschriftung festlegen.

21
mattt

In diesem Fall könnten Sie versuchen,

UILabel *displayLabel = [[UILabel alloc] initWithFrame:/*label frame*/];
displayLabel.font = [UIFont boldSystemFontOfSize:/*bold font size*/];

NSMutableAttributedString *notifyingStr = [[NSMutableAttributedString alloc] initWithString:@"Updated: 2012/10/14 21:59 PM"];
[notifyingStr beginEditing];
[notifyingStr addAttribute:NSFontAttributeName
                     value:[UIFont systemFontOfSize:/*normal font size*/]
                     range:NSMakeRange(8,10)/*range of normal string, e.g. 2012/10/14*/];
[notifyingStr endEditing];

displayLabel.attributedText = notifyingStr; // or [displayLabel setAttributedText: notifyingStr];
12
x4h1d

Text fett und unterstrichen in einem UILabel. Fügen Sie einfach die folgenden Zeilen in Ihren Code ein.

NSRange range1 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_terms", @"")];
NSRange range2 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_policy", @"")];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:lblTermsAndCondition.text];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
                        range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
                        range:range2];


[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
                  value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
                  range:range1];

[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
                       value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
                       range:range2];



lblTermsAndCondition.attributedText = attributedText;
8
Ankit Goyal

Verwenden Sie den folgenden Code. Ich hoffe es hilft dir.

NSString *[email protected]"BOOK";
NSString *display_string=[NSString stringWithFormat:@"This is %@",book];

NSMutableAttributedString *attri_str=[[NSMutableAttributedString alloc]initWithString:display_string];

int begin=[display_string length]-[needToChangeStr length];
int end=[needToChangeStr length];


[attri_str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:30] range:NSMakeRange(begin, end)];
5
user1025285

Hoffe, dieser wird Ihre Bedürfnisse erfüllen. Geben Sie die Zeichenfolge an, die als Eingabe verarbeitet werden soll, und geben Sie die Wörter an, die als Eingabe fett/farbig sein sollen.

func attributedString(parentString:String, arrayOfStringToProcess:[String], color:UIColor) -> NSAttributedString
{
    let parentAttributedString = NSMutableAttributedString(string:parentString, attributes:nil)
    let parentStringWords = parentAttributedString.string.components(separatedBy: " ")
    if parentStringWords.count != 0
    {
        let wordSearchArray = arrayOfStringToProcess.filter { inputArrayIndex in
            parentStringWords.contains(where: { $0 == inputArrayIndex }
            )}
        for eachWord in wordSearchArray
        {
            parentString.enumerateSubstrings(in: parentString.startIndex..<parentString.endIndex, options: .byWords)
            {
                (substring, substringRange, _, _) in
                if substring == eachWord
                {
                    parentAttributedString.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 15), range: NSRange(substringRange, in: parentString))
                    parentAttributedString.addAttribute(.foregroundColor, value: color, range: NSRange(substringRange, in: parentString))
                }
            }
        }
    }
    return parentAttributedString
}

Danke. Fröhliche Codierung.

3
Alex

Swift 4:

// attribute with color red and Bold
var attrs1 = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedStringKey.foregroundColor: UIColor.red]

// attribute with color black and Non Bold
var attrs2 = [NSAttributedStringKey.font: UIFont(name: "Roboto-Regular", size: 20), NSAttributedStringKey.foregroundColor: UIColor.black]  

var color1 = NSAttributedString(string: "RED", attributes: attrs1)

var color2 = NSAttributedString(string: " BLACK", attributes: attrs2)

var string = NSMutableAttributedString()

string.append(color1)

string.append(color2)

// print the text with **RED** BLACK
print("Final String : \(string)")
3
Vinu Jacob

Mit dem folgenden Code, den ich gerade in meinem Projekt implementiert habe (in Swift), ist NSRange nicht erforderlich:

    //Code sets label (yourLabel)'s text to "Tap and hold(BOLD) button to start recording."
    let boldAttribute = [
        //You can add as many attributes as you want here.
        NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: 18.0)!]

    let regularAttribute = [
        NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!]

    let beginningAttributedString = NSAttributedString(string: "Tap and ", attributes: regularAttribute )
    let boldAttributedString = NSAttributedString(string: "hold ", attributes: boldAttribute)
    let endAttributedString = NSAttributedString(string: "button to start recording.", attributes: regularAttribute )
    let fullString =  NSMutableAttributedString()

    fullString.appendAttributedString(beginningAttributedString)
    fullString.appendAttributedString(boldAttributedString)
    fullString.appendAttributedString(endAttributedString)

    yourLabel.attributedText = fullString
2
Josh O'Connor

Wenn Sie die Verwendung von Attributed Strings vereinfachen möchten, versuchen Sie es mit Attributed String Creator, der den Code für Sie generiert. https://iTunes.Apple.com/us/app/attributed-string-creator/id730928349

1
Mark Bridges