Comment utiliser l'indice et le exposant dans Swift
je veux que mon UILabel pour afficher du texte dans la manière suivante 6.022*10 23. Quelles fumctions swift a-t-il pour l'indice et l'exposant?
8 réponses
la plupart des réponses+exemples sont dans ObjC, mais c'est la façon de le faire dans Swift.
let font:UIFont? = UIFont(name: "Helvetica", size:20)
let fontSuper:UIFont? = UIFont(name: "Helvetica", size:10)
let attString:NSMutableAttributedString = NSMutableAttributedString(string: "6.022*1023", attributes: [.font:font!])
attString.setAttributes([.font:fontSuper!,.baselineOffset:10], range: NSRange(location:8,length:2))
labelVarName.attributedText = attString
Cela me donne:
Dans une explication plus détaillée:
- Get
UIFont
vous voulez à la fois le style par défaut et le style superscript, le superscript doit être plus petit. - Créer un
NSMutableAttributedString
avec la chaîne complète et la police par défaut. - Ajouter un attribut aux caractères que vous voulez changer (
NSRange
), avec les plus petits/indiceUIFont
etNSBaselineOffsetAttributeName
la valeur est le montant que vous souhaitez décaler verticalement. - Attribuer à votre
UILabel
J'espère que cela aidera D'autres Devs Swift car j'en avais aussi besoin.
une approche différente, j'ai écrit une fonction qui prend une chaîne de caractères où les exposants sont précédées ^
2^2•3•5^2
et renvoie 2²•3•5²
func exponentize(str: String) -> String {
let supers = [
"1": "\u{00B9}",
"2": "\u{00B2}",
"3": "\u{00B3}",
"4": "\u{2074}",
"5": "\u{2075}",
"6": "\u{2076}",
"7": "\u{2077}",
"8": "\u{2078}",
"9": "\u{2079}"]
var newStr = ""
var isExp = false
for (_, char) in str.characters.enumerate() {
if char == "^" {
isExp = true
} else {
if isExp {
let key = String(char)
if supers.keys.contains(key) {
newStr.append(Character(supers[key]!))
} else {
isExp = false
newStr.append(char)
}
} else {
newStr.append(char)
}
}
}
return newStr
}
c'est un peu une méthode de force brute, mais cela fonctionne si vous ne voulez pas traiter les chaînes attribuées ou si vous voulez que votre chaîne soit indépendante d'une police.
j'ai écrit l'extension suivante, ou vous pouvez l'utiliser comme une fonction, il fonctionne bien pour moi . vous pouvez la modifier en sautant les parties qui ne sont pas essentielles pour vous
extension NSMutableAttributedString
{
enum scripting : Int
{
case aSub = -1
case aSuper = 1
}
func characterSubscriptAndSuperscript(string:String,
characters:[Character],
type:scripting,
fontSize:CGFloat,
scriptFontSize:CGFloat,
offSet:Int,
length:[Int],
alignment:NSTextAlignment)-> NSMutableAttributedString
{
let paraghraphStyle = NSMutableParagraphStyle()
// Set The Paragraph aligmnet , you can ignore this part and delet off the function
paraghraphStyle.alignment = alignment
var scriptedCharaterLocation = Int()
//Define the fonts you want to use and sizes
let stringFont = UIFont.boldSystemFont(ofSize: fontSize)
let scriptFont = UIFont.boldSystemFont(ofSize: scriptFontSize)
// Define Attributes of the text body , this part can be removed of the function
let attString = NSMutableAttributedString(string:string, attributes: [NSFontAttributeName:stringFont,NSForegroundColorAttributeName:UIColor.black,NSParagraphStyleAttributeName: paraghraphStyle])
// the enum is used here declaring the required offset
let baseLineOffset = offSet * type.rawValue
// enumerated the main text characters using a for loop
for (i,c) in string.characters.enumerated()
{
// enumerated the array of first characters to subscript
for (theLength,aCharacter) in characters.enumerated()
{
if c == aCharacter
{
// Get to location of the first character
scriptedCharaterLocation = i
//Now set attributes starting from the character above
attString.setAttributes([NSFontAttributeName:scriptFont,
// baseline off set from . the enum i.e. +/- 1
NSBaselineOffsetAttributeName:baseLineOffset,
NSForegroundColorAttributeName:UIColor.black],
// the range from above location
range:NSRange(location:scriptedCharaterLocation,
// you define the length in the length array
// if subscripting at different location
// you need to define the length for each one
length:length[theLength]))
}
}
}
return attString}
}
exemples:
let attStr1 = NSMutableAttributedString().characterSubscriptAndSuperscript(
string: "23 x 456",
characters:["3","5"],
type: .aSuper,
fontSize: 20,
scriptFontSize: 15,
offSet: 10,
length: [1,2],
alignment: .left)
let attStr2 = NSMutableAttributedString().characterSubscriptAndSuperscript(
string: "H2SO4",
characters: ["2","4"],
type: .aSub,
fontSize: 20,
scriptFontSize: 15,
offSet: 8,
length: [1,1],
alignment: .left)
si vous pouvez vous entendre avec un texte qui n'a pas l'air parfait, et n'a besoin que d'un sous-ensemble de caractères, vous pouvez utiliser les numéros unicode superscript et subscript: Cela a l'avantage d'être beaucoup moins lourd.
solution Swift simple à utiliser, vous pouvez checkout HandyUIKit. Après l'avoir importé dans votre projet (par exemple via Carthage-voir instructions dans README) vous pouvez faire quelque chose comme ceci:
import HandyUIKit
"6.022*10^{23}".superscripted(font: UIFont.systemFont(ofSize: 20, weight: .medium))
cette ligne renvoie un NSAttributedString
qui ressemblera exactement à ce que vous cherchez. attribuerUILabel
s attributedText
propriété et c'est c'!
si vous cherchez subscripting un texte, utilisez simplement subscripted(font:)
à la place. Il reconnaîtra des structures comme CO_{2}
. Il y a aussi superAndSubscripted(font:)
si vous souhaitez combiner .
voir le docs pour plus d'informations et des exemples supplémentaires.
Voici une version simple qui a une bonne gestion des erreurs et qui sera compilée dans playground.
import UIKit
func setMyLabelText(myLabel: UILabel) {
if let largeFont = UIFont(name: "Helvetica", size: 20), let superScriptFont = UIFont(name: "Helvetica", size:10) {
let numberString = NSMutableAttributedString(string: "6.022*10", attributes: [.font: largeFont])
numberString.append(NSAttributedString(string: "23", attributes: [.font: superScriptFont, .baselineOffset: 10]))
myLabel.attributedText = numberString
}
}
let myLabel = UILabel()
setMyLabelText(myLabel: myLabel)
Swift 4+ Version de la réponse de @Atka
import UIKit
extension NSMutableAttributedString {
enum Scripting : Int {
case aSub = -1
case aSuper = 1
}
func scripts(string: String,
characters: [Character],
type: Scripting,
stringFont: UIFont,
fontSize: CGFloat,
scriptFont: UIFont,
scriptFontSize: CGFloat,
offSet: Int,
length: [Int],
alignment: NSTextAlignment) -> NSMutableAttributedString {
let paraghraphStyle = NSMutableParagraphStyle()
paraghraphStyle.alignment = alignment
var scriptedCharaterLocation = Int()
let attributes = [
NSAttributedStringKey.font: stringFont,
NSAttributedStringKey.foregroundColor: UIColor.black,
NSAttributedStringKey.paragraphStyle: paraghraphStyle
]
let attString = NSMutableAttributedString(string:string, attributes: attributes)
let baseLineOffset = offSet * type.rawValue
let scriptTextAttributes: [NSAttributedStringKey : Any] = [
NSAttributedStringKey.font: scriptFont,
NSAttributedStringKey.baselineOffset: baseLineOffset,
NSAttributedStringKey.foregroundColor: UIColor.blue
]
for (i,c) in string.enumerated() {
for (theLength, aCharacter) in characters.enumerated() {
if c == aCharacter {
scriptedCharaterLocation = i
attString.setAttributes(scriptTextAttributes, range: NSRange(location:scriptedCharaterLocation,
length: length[theLength]))
}
}
}
return attString
}
}
une jolie fonction simple qui affiche un nombre comme texte en exposant.
func exponent(i: Int) -> String {
let powers : [String] = [
"\u{2070}",
"\u{00B9}",
"\u{00B2}",
"\u{00B3}",
"\u{2074}",
"\u{2075}",
"\u{2076}",
"\u{2077}",
"\u{2078}",
"\u{2079}"
]
let digits = Array(String(i))
var string = ""
for d in digits {
string.append("\(powers[Int(String(d))!])")
}
return string
}