Rendre le texte en gras à l'aide d'une chaîne attribuée dans Swift

100

J'ai une chaîne comme celle-ci

var str = "@text1 this is good @text1"

Maintenant, remplacez-le text1par une autre chaîne, par exemple t 1. Je peux remplacer le texte, mais je ne peux pas le mettre en gras. Je veux mettre en gras la nouvelle chaîne t 1, de sorte que la sortie finale soit:

@t 1 c'est bien @t 1

Comment puis-je le faire?

Tous les exemples que je vois sont en Objective-C, mais je veux le faire dans Swift.

Merci d'avance.

user2413621
la source
1
Vous devez décomposer votre problème: Apprenez à «mettre en gras»: stackoverflow.com/questions/25199580/… Apprenez à remplacer du texte.
Larme
1
Utilisez cette bibliothèque, c'est assez simple. github.com/iOSTechHub/AttributedString
Ashish Chauhan

Réponses:

237

Usage:

let label = UILabel()
label.attributedText =
    NSMutableAttributedString()
        .bold("Address: ")
        .normal(" Kathmandu, Nepal\n\n")
        .orangeHighlight(" Email: ")
        .blackHighlight(" [email protected] ")
        .bold("\n\nCopyright: ")
        .underlined(" All rights reserved. 2020.")

Résultat:

entrez la description de l'image ici

Voici une manière intéressante de créer une combinaison de textes gras et normaux dans une seule étiquette ainsi que d'autres méthodes bonus.

Extension: Swift 5. *

extension NSMutableAttributedString {
    var fontSize:CGFloat { return 14 }
    var boldFont:UIFont { return UIFont(name: "AvenirNext-Bold", size: fontSize) ?? UIFont.boldSystemFont(ofSize: fontSize) }
    var normalFont:UIFont { return UIFont(name: "AvenirNext-Regular", size: fontSize) ?? UIFont.systemFont(ofSize: fontSize)}

    func bold(_ value:String) -> NSMutableAttributedString {

        let attributes:[NSAttributedString.Key : Any] = [
            .font : boldFont
        ]

        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }

    func normal(_ value:String) -> NSMutableAttributedString {

        let attributes:[NSAttributedString.Key : Any] = [
            .font : normalFont,
        ]

        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
    /* Other styling methods */
    func orangeHighlight(_ value:String) -> NSMutableAttributedString {

        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .foregroundColor : UIColor.white,
            .backgroundColor : UIColor.orange
        ]

        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }

    func blackHighlight(_ value:String) -> NSMutableAttributedString {

        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .foregroundColor : UIColor.white,
            .backgroundColor : UIColor.black

        ]

        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }

    func underlined(_ value:String) -> NSMutableAttributedString {

        let attributes:[NSAttributedString.Key : Any] = [
            .font :  normalFont,
            .underlineStyle : NSUnderlineStyle.single.rawValue

        ]

        self.append(NSAttributedString(string: value, attributes:attributes))
        return self
    }
}
Prajeet Shrestha
la source
n'est-ce pas pour Swift 2?
remy boys
2
Un petit plus: func bold(_ text:String, _ size:CGFloat). J'ai ajouté de la taille au gras pour pouvoir le contrôler de l'extérieur. De plus, j'ai manqué la AvenirNext-Mediumpolice dans cette fonction, il m'a donc fallu quelques minutes pour comprendre pourquoi je ne peux pas voir ma police. La tête haute.
Gal
tu as sauvé ma journée, mec!
oskarko
Merci! A travaillé comme un charme :)
Sharad Chauhan
1
Ballay ballay sarkaaar: D
Mohsin Khubaib Ahmed
102
var normalText = "Hi am normal"

var boldText  = "And I am BOLD!"

var attributedString = NSMutableAttributedString(string:normalText)

var attrs = [NSFontAttributeName : UIFont.boldSystemFont(ofSize: 15)]
var boldString = NSMutableAttributedString(string: boldText, attributes:attrs)

attributedString.append(boldString)

Lorsque vous souhaitez l'attribuer à une étiquette:

yourLabel.attributedText = attributedString
Dejan Skledar
la source
Réponse géniale! Merci!
hacker_1989
Remarque: appendAttributedString a été renommé en .append ()
Andrea Leganza
28

modifier / mettre à jour: Xcode 8.3.2 • Swift 3.1

Si vous connaissez HTML et CSS, vous pouvez l'utiliser pour contrôler facilement le style de police, la couleur et la taille de votre chaîne attribuée comme suit:

extension String {
    var html2AttStr: NSAttributedString? {
        return try? NSAttributedString(data: Data(utf8), options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue], documentAttributes: nil)
    }
}

"<style type=\"text/css\">#red{color:#F00}#green{color:#0F0}#blue{color: #00F; font-weight: Bold; font-size: 32}</style><span id=\"red\" >Red,</span><span id=\"green\" > Green </span><span id=\"blue\">and Blue</span>".html2AttStr
Leo Dabus
la source
J'essaie de mettre en œuvre cela dans Swift 2 Xcode, mais la police n'est pas appliquée. Voici la chaîne: <link href=\"https://fonts.googleapis.com/css?family=Frank+Ruhl+Libre\" rel=\"stylesheet\"> <span style=\"font-family: 'Frank Ruhl Libre', sans-serif;\">שלום</span>
DaniSmithProductions
Si le style utilise WebKit pour analyser les chaînes HTML dans NSAttributedString, faites attention de l'utiliser dans un thread d'arrière-plan ...
FouZ
Quels sont les avantages d'utiliser cette approche plutôt que la réponse @prajeet?
Emre Önder
17

Si vous travaillez avec des chaînes localisées, vous ne pourrez peut-être pas compter sur la chaîne en gras toujours à la fin de la phrase. Si tel est le cas, ce qui suit fonctionne bien:

Par exemple, la requête "bla" ne correspond à aucun élément

/* Create the search query part of the text, e.g. "blah". 
   The variable 'text' is just the value entered by  the user. */
let searchQuery = "\"\(text)\""

/* Put the search text into the message */
let message = "Query \(searchQuery). does not match any items"

/* Find the position of the search string. Cast to NSString as we want
   range to be of type NSRange, not Swift's Range<Index> */
let range = (message as NSString).rangeOfString(searchQuery)

/* Make the text at the given range bold. Rather than hard-coding a text size,
   Use the text size configured in Interface Builder. */
let attributedString = NSMutableAttributedString(string: message)
attributedString.addAttribute(NSFontAttributeName, value: UIFont.boldSystemFontOfSize(label.font.pointSize), range: range)

/* Put the text in a label */
label.attributedText = attributedString
Ian
la source
2
Après des heures de recherche, c'est la seule réponse qui a trouvé une solution à mon problème. +1
Super_Simon
9

J'ai étendu la bonne réponse de David West afin que vous puissiez saisir une chaîne et lui indiquer toutes les sous-chaînes que vous souhaitez enhardir:

func addBoldText(fullString: NSString, boldPartsOfString: Array<NSString>, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
    let nonBoldFontAttribute = [NSFontAttributeName:font!]
    let boldFontAttribute = [NSFontAttributeName:boldFont!]
    let boldString = NSMutableAttributedString(string: fullString as String, attributes:nonBoldFontAttribute)
    for i in 0 ..< boldPartsOfString.count {
        boldString.addAttributes(boldFontAttribute, range: fullString.rangeOfString(boldPartsOfString[i] as String))
    }
    return boldString
}

Et puis appelez-le comme ceci:

let normalFont = UIFont(name: "Dosis-Medium", size: 18)
let boldSearchFont = UIFont(name: "Dosis-Bold", size: 18)
self.UILabel.attributedText = addBoldText("Check again in 30 days to find more friends", boldPartsOfString: ["Check", "30 days", "find", "friends"], font: normalFont!, boldFont: boldSearchFont!)

Cela enhardira toutes les sous-chaînes que vous souhaitez mettre en gras dans votre chaîne donnée

Jeremy Bader
la source
Est-il possible d'avoir le même mot en gras à deux endroits différents? EX: "Vérifiez à nouveau dans 30 jours pour trouver 30 amis". Comment rendre les deux "30" gras? Merci d'avance.
Dian
8

C'est le meilleur moyen que j'ai trouvé. Ajoutez une fonction que vous pouvez appeler de n'importe où et ajoutez-la à un fichier sans classe comme Constants.swift, puis vous pouvez enhardir les mots dans n'importe quelle chaîne, à de nombreuses reprises en appelant juste UNE LIGNE de code:

Pour aller dans un fichier constants.swift:

import Foundation
import UIKit

func addBoldText(fullString: NSString, boldPartOfString: NSString, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
   let nonBoldFontAttribute = [NSFontAttributeName:font!]
   let boldFontAttribute = [NSFontAttributeName:boldFont!]
   let boldString = NSMutableAttributedString(string: fullString as String, attributes:nonBoldFontAttribute)
   boldString.addAttributes(boldFontAttribute, range: fullString.rangeOfString(boldPartOfString as String))
   return boldString
}

Ensuite, vous pouvez simplement appeler cette ligne de code pour n'importe quel UILabel:

self.UILabel.attributedText = addBoldText("Check again in 30 DAYS to find more friends", boldPartOfString: "30 DAYS", font: normalFont!, boldFont: boldSearchFont!)


//Mark: Albeit that you've had to define these somewhere:

let normalFont = UIFont(name: "INSERT FONT NAME", size: 15)
let boldFont = UIFont(name: "INSERT BOLD FONT", size: 15)
David West
la source
8

S'appuyant sur les excellentes réponses de Jeremy Bader et David West, une extension Swift 3:

extension String {
    func withBoldText(boldPartsOfString: Array<NSString>, font: UIFont!, boldFont: UIFont!) -> NSAttributedString {
        let nonBoldFontAttribute = [NSFontAttributeName:font!]
        let boldFontAttribute = [NSFontAttributeName:boldFont!]
        let boldString = NSMutableAttributedString(string: self as String, attributes:nonBoldFontAttribute)
        for i in 0 ..< boldPartsOfString.count {
            boldString.addAttributes(boldFontAttribute, range: (self as NSString).range(of: boldPartsOfString[i] as String))
        }
        return boldString
    }
}

Usage:

let label = UILabel()
let font = UIFont(name: "AvenirNext-Italic", size: 24)!
let boldFont = UIFont(name: "AvenirNext-BoldItalic", size: 24)!
label.attributedText = "Make sure your face is\nbrightly and evenly lit".withBoldText(
    boldPartsOfString: ["brightly", "evenly"], font: font, boldFont: boldFont)
Daniel McLean
la source
5

usage....

let attrString = NSMutableAttributedString()
            .appendWith(weight: .semibold, "almost bold")
            .appendWith(color: .white, weight: .bold, " white and bold")
            .appendWith(color: .black, ofSize: 18.0, " big black")

deux centimes...

extension NSMutableAttributedString {

    @discardableResult func appendWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString{
        let attrText = NSAttributedString.makeWith(color: color, weight: weight, ofSize:ofSize, text)
        self.append(attrText)
        return self
    }

}
extension NSAttributedString {

    public static func makeWith(color: UIColor = UIColor.darkText, weight: UIFont.Weight = .regular, ofSize: CGFloat = 12.0, _ text: String) -> NSMutableAttributedString {

        let attrs = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: ofSize, weight: weight), NSAttributedStringKey.foregroundColor: color]
        return NSMutableAttributedString(string: text, attributes:attrs)
    }
}
Samuel
la source
1
iOS 11 ou supérieur (en raison de l'utilisation d'UIFont.Weight).
Andrea Leganza
4

En acceptant comme valide la réponse de Prajeet Shrestha dans ce fil, je voudrais étendre sa solution en utilisant le Label s'il est connu et les traits de la police.

Swift 4

extension NSMutableAttributedString {

    @discardableResult func normal(_ text: String) -> NSMutableAttributedString {
        let normal = NSAttributedString(string: text)
        append(normal)

        return self
    }

    @discardableResult func bold(_ text: String, withLabel label: UILabel) -> NSMutableAttributedString {

        //generate the bold font
        var font: UIFont = UIFont(name: label.font.fontName , size: label.font.pointSize)!
        font = UIFont(descriptor: font.fontDescriptor.withSymbolicTraits(.traitBold) ?? font.fontDescriptor, size: font.pointSize)

        //generate attributes
        let attrs: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font]
        let boldString = NSMutableAttributedString(string:text, attributes: attrs)

        //append the attributed text
        append(boldString)

        return self
    }
}
JSR - Silicornio
la source
4

Swift 4 et supérieur

Pour Swift 4 et supérieur, c'est un bon moyen:

    let attributsBold = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .bold)]
    let attributsNormal = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16, weight: .regular)]
    var attributedString = NSMutableAttributedString(string: "Hi ", attributes:attributsNormal)
    let boldStringPart = NSMutableAttributedString(string: "John", attributes:attributsBold)
    attributedString.append(boldStringPart)
  
    yourLabel.attributedText = attributedString

Dans l'étiquette, le texte ressemble à: "Salut John "

Jonas Deichelmann
la source
3

Un moyen très simple de le faire.

    let text = "This string is having multiple font"
    let attributedText = 
    NSMutableAttributedString.getAttributedString(fromString: text)

    attributedText.apply(font: UIFont.boldSystemFont(ofSize: 24), subString: 
    "This")

    attributedText.apply(font: UIFont.boldSystemFont(ofSize: 24), onRange: 
    NSMakeRange(5, 6))

Pour plus de détails, cliquez ici: https://github.com/iOSTechHub/AttributedString

Ashish Chauhan
la source
Que diriez-vous de semi gras?
Houman
Cela devrait être la réponse acceptée. @Houman utilisez la bibliothèque ci-dessus et utilisez la applyméthode avec la police que vous voulez
Zack Shapiro
2

Cela pourrait être utile

class func createAttributedStringFrom (string1 : String ,strin2 : String, attributes1 : Dictionary<String, NSObject>, attributes2 : Dictionary<String, NSObject>) -> NSAttributedString{

let fullStringNormal = (string1 + strin2) as NSString
let attributedFullString = NSMutableAttributedString(string: fullStringNormal as String)

attributedFullString.addAttributes(attributes1, range: fullStringNormal.rangeOfString(string1))
attributedFullString.addAttributes(attributes2, range: fullStringNormal.rangeOfString(strin2))
return attributedFullString
}
Martin Jacob
la source
2

Swift 3.0

Convertissez le HTML en chaîne et changez de police selon vos besoins.

do {

     let str = try NSAttributedString(data: ("I'm a normal text and <b>this is my bold part . </b>And I'm again in the normal text".data(using: String.Encoding.unicode, allowLossyConversion: true)!), options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)

     myLabel.attributedText = str
     myLabel.font =  MONTSERRAT_BOLD(23)
     myLabel.textAlignment = NSTextAlignment.left
} catch {
     print(error)
}


func MONTSERRAT_BOLD(_ size: CGFloat) -> UIFont
{
    return UIFont(name: "MONTSERRAT-BOLD", size: size)!
}
Mitul Marsoniya
la source
Vous devez convertir votre chaîne en données en utilisant utf8. Notez que Data est conforme à la collection dans Swift 3 afin que vous puissiez initialiser Data avec votre chaîne de vue de collection utf8 Data("I'm a normal text and <b>this is my bold part . </b>And I'm again in the normal text".utf8)et définir le codage des caractères dans les options[NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: String.Encoding.utf8.rawValue]
Leo Dabus
0

Utilisez simplement un code comme celui-ci:

 let font = UIFont(name: "Your-Font-Name", size: 10.0)!

        let attributedText = NSMutableAttributedString(attributedString: noteLabel.attributedText!)
        let boldedRange = NSRange(attributedText.string.range(of: "Note:")!, in: attributedText.string)
        attributedText.addAttributes([NSAttributedString.Key.font : font], range: boldedRange)
        noteLabel.attributedText = attributedText
Michał Ziobro
la source
0

deux liner dans swift 4:

            button.setAttributedTitle(.init(string: "My text", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .bold)]), for: .selected)
            button.setAttributedTitle(.init(string: "My text", attributes: [.font: UIFont.systemFont(ofSize: 20, weight: .regular)]), for: .normal)
Antzi
la source
0

Swift 5.1 utilise NSAttributedString.Keyau lieu deNSAttributedStringKey

let test1Attributes:[NSAttributedString.Key: Any] = [.font : UIFont(name: "CircularStd-Book", size: 14)!]
let test2Attributes:[NSAttributedString.Key: Any] = [.font : UIFont(name: "CircularStd-Bold", size: 16)!]

let test1 = NSAttributedString(string: "\(greeting!) ", attributes:test1Attributes)
let test2 = NSAttributedString(string: firstName!, attributes:test2Attributes)
let text = NSMutableAttributedString()

text.append(test1)
text.append(test2)
return text
Yodagama
la source
0

Pour -> Recherche Télévision par taille

Unidirectionnel utilisant NString et sa plage

let query = "Television"
let headerTitle = "size"
let message = "Search \(query) by \(headerTitle)"
let range = (message as NSString).range(of: query)
let attributedString = NSMutableAttributedString(string: message)
attributedString.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: label1.font.pointSize), range: range)
label1.attributedText = attributedString

un autre sans utiliser NString et sa gamme

let query = "Television"
let headerTitle = "size"
let (searchText, byText) = ("Search ", " by \(headerTitle)")
let attributedString = NSMutableAttributedString(string: searchText)
let byTextAttributedString = NSMutableAttributedString(string: byText)
let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: label1.font.pointSize)]
let boldString = NSMutableAttributedString(string: query, attributes:attrs)
attributedString.append(boldString)
attributedString.append(byTextAttributedString)
label1.attributedText = attributedString

swift5

Vinoth Anandan
la source
-1

Améliorer la réponse de Prajeet Shrestha: -

Vous pouvez créer une extension générique pour NSMutableAttributedString qui implique moins de code. Dans ce cas, j'ai choisi d'utiliser la police système, mais vous pouvez l'adapter afin de pouvoir saisir le nom de la police en tant que paramètre.

    extension NSMutableAttributedString {

        func systemFontWith(text: String, size: CGFloat, weight: CGFloat) -> NSMutableAttributedString {
            let attributes: [String: AnyObject] = [NSFontAttributeName: UIFont.systemFont(ofSize: size, weight: weight)]
            let string = NSMutableAttributedString(string: text, attributes: attributes)
            self.append(string)
            return self
        }
    }
Edward
la source
-1

Vous pouvez le faire en utilisant la méthode personnalisée simple décrite ci-dessous. Vous devez donner la chaîne entière dans le premier paramètre et le texte en gras dans le deuxième paramètre. J'espère que cela aidera.

func getAttributedBoldString(str : String, boldTxt : String) -> NSMutableAttributedString {
        let attrStr = NSMutableAttributedString.init(string: str)
        let boldedRange = NSRange(str.range(of: boldTxt)!, in: str)
        attrStr.addAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 17, weight: .bold)], range: boldedRange)
        return attrStr
    }

utilisation: initalString = Je suis un garçon

label.attributedText = getAttributedBoldString (str: initalString, boldTxt: "Garçon")

chaîne résultante = je suis un garçon

Muhammad Haroon Iqbal
la source