J'essaie de faire une simple calculatrice de café. Je dois afficher la quantité de café en grammes. Le symbole "g" pour les grammes doit être attaché à mon UILabel que j'utilise pour afficher le montant. Les numéros dans UILabel changent dynamiquement avec la saisie de l'utilisateur, mais je dois ajouter un "g" en minuscule à la fin de la chaîne qui est formatée différemment des nombres mis à jour. Le "g" doit être attaché aux nombres afin que, à mesure que la taille et la position du nombre changent, le "g" "se déplace" avec les nombres. Je suis sûr que ce problème a déjà été résolu, donc un lien dans la bonne direction serait utile, car j'ai cherché mon petit coeur sur Google.
J'ai cherché dans la documentation une chaîne attribuée et j'ai même téléchargé un "Créateur de chaîne attribuée" depuis l'App Store, mais le code obtenu est en Objective-C et j'utilise Swift. Ce qui serait génial, et probablement utile aux autres développeurs apprenant ce langage, est un exemple clair de création d'une police personnalisée avec des attributs personnalisés à l'aide d'une chaîne attribuée à Swift. La documentation à ce sujet est très déroutante car il n’ya pas de chemin clair à suivre. Mon plan est de créer la chaîne attribuée et de l'ajouter à la fin de ma chaîne coffeeAmount.
var coffeeAmount: String = calculatedCoffee + attributedText
Où calculeCoffee est un Int converti en chaîne et "attributText" est le minuscule "g" avec la police personnalisée que je tente de créer. Peut-être que je m'y prends mal. Toute aide est appréciée!
Cette réponse a été mise à jour pour Swift 4.2.
La forme générale pour créer et définir une chaîne attribuée est comme ceci. Vous pouvez trouver d'autres options communes ci-dessous.
// create attributed string
let myString = "Swift Attributed String"
let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.blue ]
let myAttrString = NSAttributedString(string: myString, attributes: myAttribute)
// set attributed text on a UILabel
myLabel.attributedText = myAttrString
let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.blue ]
let myAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
let myAttribute = [ NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 18.0)! ]
let myAttribute = [ NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue ]
let myShadow = NSShadow()
myShadow.shadowBlurRadius = 3
myShadow.shadowOffset = CGSize(width: 3, height: 3)
myShadow.shadowColor = UIColor.gray
let myAttribute = [ NSAttributedString.Key.shadow: myShadow ]
Le reste de cet article donne plus de détails pour ceux qui sont intéressés.
Les attributs de chaîne ne sont qu'un dictionnaire sous la forme de [NSAttributedString.Key: Any]
, où NSAttributedString.Key
est le nom de clé de l'attribut et Any
est la valeur d'un type. La valeur peut être une police, une couleur, un entier ou autre chose. De nombreux attributs standard dans Swift ont déjà été prédéfinis. Par exemple:
NSAttributedString.Key.font
, valeur: une UIFont
NSAttributedString.Key.foregroundColor
, valeur: une UIColor
NSAttributedString.Key.link
, valeur: une NSURL
ou NSString
Il y en a beaucoup d'autres. Voir ce lien pour plus d'informations. Vous pouvez même créer vos propres attributs personnalisés, tels que:
nom de clé: NSAttributedString.Key.myName
, valeur: un type.
si vous faites un extension :
extension NSAttributedString.Key {
static let myName = NSAttributedString.Key(rawValue: "myCustomAttributeKey")
}
Vous pouvez déclarer des attributs comme si vous déclariez un autre dictionnaire.
// single attributes declared one at a time
let singleAttribute1 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let singleAttribute2 = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
let singleAttribute3 = [ NSAttributedString.Key.underlineStyle: NSUnderlineStyle.double.rawValue ]
// multiple attributes declared at once
let multipleAttributes: [NSAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: UIColor.green,
NSAttributedString.Key.backgroundColor: UIColor.yellow,
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.double.rawValue ]
// custom attribute
let customAttribute = [ NSAttributedString.Key.myName: "Some value" ]
Notez la rawValue
qui était nécessaire pour la valeur du style souligné.
Comme les attributs ne sont que des dictionnaires, vous pouvez également les créer en créant un dictionnaire vide, puis en y ajoutant des paires clé-valeur. Si la valeur contient plusieurs types, vous devez alors utiliser Any
comme type. Voici l'exemple multipleAttributes
du dessus, recréé de cette façon:
var multipleAttributes = [NSAttributedString.Key : Any]()
multipleAttributes[NSAttributedString.Key.foregroundColor] = UIColor.green
multipleAttributes[NSAttributedString.Key.backgroundColor] = UIColor.yellow
multipleAttributes[NSAttributedString.Key.underlineStyle] = NSUnderlineStyle.double.rawValue
Maintenant que vous comprenez les attributs, vous pouvez créer des chaînes attribuées.
Initialisation
Il existe plusieurs façons de créer des chaînes attribuées. Si vous avez juste besoin d'une chaîne en lecture seule, vous pouvez utiliser NSAttributedString
. Voici quelques façons de l'initialiser:
// Initialize with a string only
let attrString1 = NSAttributedString(string: "Hello.")
// Initialize with a string and inline attribute(s)
let attrString2 = NSAttributedString(string: "Hello.", attributes: [NSAttributedString.Key.myName: "A value"])
// Initialize with a string and separately declared attribute(s)
let myAttributes1 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let attrString3 = NSAttributedString(string: "Hello.", attributes: myAttributes1)
Si vous devez modifier les attributs ou le contenu de la chaîne ultérieurement, vous devez utiliser NSMutableAttributedString
. Les déclarations sont très similaires:
// Create a blank attributed string
let mutableAttrString1 = NSMutableAttributedString()
// Initialize with a string only
let mutableAttrString2 = NSMutableAttributedString(string: "Hello.")
// Initialize with a string and inline attribute(s)
let mutableAttrString3 = NSMutableAttributedString(string: "Hello.", attributes: [NSAttributedString.Key.myName: "A value"])
// Initialize with a string and separately declared attribute(s)
let myAttributes2 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let mutableAttrString4 = NSMutableAttributedString(string: "Hello.", attributes: myAttributes2)
Par exemple, créons la chaîne attribuée en haut de cet article.
Créez d’abord une NSMutableAttributedString
avec un nouvel attribut de police.
let myAttribute = [ NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 18.0)! ]
let myString = NSMutableAttributedString(string: "Swift", attributes: myAttribute )
Si vous continuez, définissez la chaîne attribuée sur une UITextView
(ou UILabel
) comme ceci:
textView.attributedText = myString
Vous ne pas utiliser textView.text
.
Voici le résultat:
Ajoutez ensuite une autre chaîne attribuée sans attribut. (Notez que même si j’ai utilisé let
pour déclarer myString
ci-dessus, je peux toujours le modifier car c’est un NSMutableAttributedString
. Cela me semble plutôt inhabituel et je ne serais pas surpris que cela change à l’avenir. Laissez-moi un commentaire. arrive.)
let attrString = NSAttributedString(string: " Attributed Strings")
myString.append(attrString)
Ensuite, nous allons simplement sélectionner le mot "Strings", qui commence à l’index 17
et a une longueur de 7
. Notez qu'il s'agit d'une NSRange
et non d'une Swift Range
. (Voir cette réponse pour en savoir plus sur les plages.) La méthode addAttribute
nous permet de placer le nom de la clé d'attribut au premier emplacement, la valeur de l'attribut au deuxième emplacement et la plage au troisième.
var myRange = NSRange(location: 17, length: 7) // range starting at location 17 with a lenth of 7: "Strings"
myString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: myRange)
Enfin, ajoutons une couleur de fond. Pour varier, utilisons la méthode addAttributes
(notez la s
). Je pourrais ajouter plusieurs attributs à la fois avec cette méthode, mais je vais simplement en ajouter un à nouveau.
myRange = NSRange(location: 3, length: 17)
let anotherAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
myString.addAttributes(anotherAttribute, range: myRange)
Notez que les attributs se chevauchent à certains endroits. L'ajout d'un attribut n'écrase pas un attribut déjà présent.
Swift utilise la même NSMutableAttributedString
qu'Obj-C. Vous l'instanciez en transmettant la valeur calculée sous forme de chaîne:
var attributedString = NSMutableAttributedString(string:"\(calculatedCoffee)")
Créez maintenant la chaîne g
attribuée (heh). Remarque: UIFont.systemFontOfSize(_)
est maintenant un initialiseur disponible. Il doit donc être déballé avant de pouvoir être utilisé:
var attrs = [NSFontAttributeName : UIFont.systemFontOfSize(19.0)!]
var gString = NSMutableAttributedString(string:"g", attributes:attrs)
Et puis l'ajouter:
attributedString.appendAttributedString(gString)
Vous pouvez ensuite paramétrer UILabel pour afficher NSAttributedString comme ceci:
myLabel.attributedText = attributedString
Swift 4:
let attributes = [NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 17)!,
NSAttributedStringKey.foregroundColor: UIColor.white]
Version Xcode 6 :
let attriString = NSAttributedString(string:"attriString", attributes:
[NSForegroundColorAttributeName: UIColor.lightGrayColor(),
NSFontAttributeName: AttriFont])
Version Xcode 9.3 :
let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedStringKey.foregroundColor: UIColor.lightGray,
NSAttributedStringKey.font: AttriFont])
Xcode 10, iOS 12, Swift 4 :
let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedString.Key.foregroundColor: UIColor.lightGray,
NSAttributedString.Key.font: AttriFont])
Swift: xcode 6.1
let font:UIFont? = UIFont(name: "Arial", size: 12.0)
let attrString = NSAttributedString(
string: titleData,
attributes: NSDictionary(
object: font!,
forKey: NSFontAttributeName))
Fonctionne bien en beta 6
let attrString = NSAttributedString(
string: "title-title-title",
attributes: NSDictionary(
object: NSFont(name: "Arial", size: 12.0),
forKey: NSFontAttributeName))
Swift 2.0
Voici un échantillon:
let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString
OR
let stringAttributes = [
NSFontAttributeName : UIFont(name: "Helvetica Neue", size: 17.0)!,
NSUnderlineStyleAttributeName : 1,
NSForegroundColorAttributeName : UIColor.orangeColor(),
NSTextEffectAttributeName : NSTextEffectLetterpressStyle,
NSStrokeWidthAttributeName : 2.0]
let atrributedString = NSAttributedString(string: "Sample String: Attributed", attributes: stringAttributes)
sampleLabel.attributedText = atrributedString
La meilleure façon d'approcher les chaînes attribuées sur iOS consiste à utiliser l'éditeur de texte attribué intégré dans le générateur d'interface et à éviter le codage en dur inutile de NSAtrributedStringKeys dans vos fichiers source.
Vous pouvez ultérieurement remplacer dynamiquement des placehoderls au moment de l'exécution en utilisant cette extension:
extension NSAttributedString {
func replacing(placeholder:String, with valueString:String) -> NSAttributedString {
if let range = self.string.range(of:placeholder) {
let nsRange = NSRange(range,in:valueString)
let mutableText = NSMutableAttributedString(attributedString: self)
mutableText.replaceCharacters(in: nsRange, with: valueString)
return mutableText as NSAttributedString
}
return self
}
}
Ajoutez une étiquette de storyboard avec un texte attribué ressemblant à ceci.
Ensuite, vous mettez simplement à jour la valeur chaque fois que vous avez besoin de ceci:
label.attributedText = initalAttributedString.replacing(placeholder: "<price>", with: newValue)
Veillez à enregistrer dans initalAttributedString la valeur d'origine.
Vous pouvez mieux comprendre cette approche en lisant cet article: https://medium.com/mobile-appetite/text-attributes-on-ios-the-effortless-approach-ff086588173e
J'ai créé un outil en ligne qui va résoudre votre problème! Vous pouvez écrire votre chaîne et appliquer des styles de manière graphique. L'outil vous fournit le code objectif-c et Swift pour générer cette chaîne.
Aussi est open source alors n'hésitez pas à l'étendre et envoyer des PR.
Swift 4
let attributes = [NSAttributedStringKey.font : UIFont(name: CustomFont.NAME_REGULAR.rawValue, size: CustomFontSize.SURVEY_FORM_LABEL_SIZE.rawValue)!]
let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
Vous devez supprimer la valeur brute dans Swift 4
Pour moi, les solutions ci-dessus ne fonctionnaient pas pour définir une couleur ou une propriété spécifique.
Cela a fonctionné:
let attributes = [
NSFontAttributeName : UIFont(name: "Helvetica Neue", size: 12.0)!,
NSUnderlineStyleAttributeName : 1,
NSForegroundColorAttributeName : UIColor.darkGrayColor(),
NSTextEffectAttributeName : NSTextEffectLetterpressStyle,
NSStrokeWidthAttributeName : 3.0]
var atriString = NSAttributedString(string: "My Attributed String", attributes: attributes)
func decorateText(sub:String, des:String)->NSAttributedString{
let textAttributesOne = [NSAttributedStringKey.foregroundColor: UIColor.darkText, NSAttributedStringKey.font: UIFont(name: "PTSans-Bold", size: 17.0)!]
let textAttributesTwo = [NSAttributedStringKey.foregroundColor: UIColor.black, NSAttributedStringKey.font: UIFont(name: "PTSans-Regular", size: 14.0)!]
let textPartOne = NSMutableAttributedString(string: sub, attributes: textAttributesOne)
let textPartTwo = NSMutableAttributedString(string: des, attributes: textAttributesTwo)
let textCombination = NSMutableAttributedString()
textCombination.append(textPartOne)
textCombination.append(textPartTwo)
return textCombination
}
//La mise en oeuvre
cell.lblFrom.attributedText = decorateText(sub: sender!, des: " - \(convertDateFormatShort3(myDateString: datetime!))")
Swift 2.1 - Xcode 7
let labelFont = UIFont(name: "HelveticaNeue-Bold", size: 18)
let attributes :[String:AnyObject] = [NSFontAttributeName : labelFont!]
let attrString = NSAttributedString(string:"foo", attributes: attributes)
myLabel.attributedText = attrString
let attrString = NSAttributedString (
string: "title-title-title",
attributes: [NSAttributedStringKey.foregroundColor: UIColor.black])
Les attributs peuvent être réglés directement dans Swift 3 ...
let attributes = NSAttributedString(string: "String", attributes: [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 30)!,
NSForegroundColorAttributeName : UIColor .white,
NSTextEffectAttributeName : NSTextEffectLetterpressStyle])
Puis utilisez la variable dans n'importe quelle classe avec des attributs
extension UILabel{
func setSubTextColor(pSubString : String, pColor : UIColor){
let attributedString: NSMutableAttributedString = self.attributedText != nil ? NSMutableAttributedString(attributedString: self.attributedText!) : NSMutableAttributedString(string: self.text!);
let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
if range.location != NSNotFound {
attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
}
self.attributedText = attributedString
}
}
Swift 4.2
extension UILabel {
func boldSubstring(_ substr: String) {
guard substr.isEmpty == false,
let text = attributedText,
let range = text.string.range(of: substr, options: .caseInsensitive) else {
return
}
let attr = NSMutableAttributedString(attributedString: text)
let start = text.string.distance(from: text.string.startIndex, to: range.lowerBound)
let length = text.string.distance(from: range.lowerBound, to: range.upperBound)
attr.addAttributes([NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: self.font.pointSize)],
range: NSMakeRange(start, length))
attributedText = attr
}
}
Ce sera vraiment facile de résoudre votre problème avec la bibliothèque que j'ai créée. Cela s'appelle Atributika.
let calculatedCoffee: Int = 768
let g = Style("g").font(.boldSystemFont(ofSize: 12)).foregroundColor(.red)
let all = Style.font(.systemFont(ofSize: 12))
let str = "\(calculatedCoffee)<g>g</g>".style(tags: g)
.styleAll(all)
.attributedString
label.attributedText = str
Vous pouvez le trouver ici https://github.com/psharanda/Atributika
Swifter Swift a une façon très douce de le faire sans aucun travail vraiment. Indiquez simplement le modèle qui doit être mis en correspondance et les attributs à appliquer. Ils sont parfaits pour beaucoup de choses, consultez-les.
``` Swift
let defaultGenreText = NSAttributedString(string: "Select Genre - Required")
let redGenreText = defaultGenreText.applying(attributes: [NSAttributedString.Key.foregroundColor : UIColor.red], toRangesMatching: "Required")
``
Si vous utilisez plusieurs endroits et que vous voulez que cela se produise uniquement dans des cas spécifiques, cette méthode ne fonctionnera pas.
Vous pouvez le faire en une étape, simplement plus facile à lire quand ils sont séparés.
Swift 5 et plus
let attributedString = NSAttributedString(string:"targetString",
attributes:[NSAttributedString.Key.foregroundColor: UIColor.lightGray,
NSAttributedString.Key.font: UIFont(name: "Arial", size: 18.0) as Any])
Swift 4.x
let attr = [NSForegroundColorAttributeName:self.configuration.settingsColor, NSFontAttributeName: self.configuration.settingsFont]
let title = NSAttributedString(string: self.configuration.settingsTitle,
attributes: attr)
Swift 3.0 // créer une chaîne attribuée
Définir des attributs comme
let attributes = [NSAttributedStringKey.font : UIFont.init(name: "Avenir-Medium", size: 13.0)]
Veuillez envisager d'utiliser Prestyler
import Prestyler
...
Prestyle.defineRule("$", UIColor.red)
label.attributedText = "\(calculatedCoffee) $g$".prestyled()