我希望我的UILabel以下列方式显示文本6.022 * 10 23 。对下标和上标有什么样的影响?
答案 0 :(得分:71)
大多数答案+示例都在ObjC中,但这是如何在Swift中完成的。
{"status":{"code":311,"message":"Service Request Successfully Queried.","cause":""},"Response":{"LastPage":"true","NumOutputObjects":"0","ListOfServiceRequest":{}}}
这给了我:
更详细的解释:
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
,上标必须更小。UIFont
。NSMutableAttributedString
为要更改的字符(NSRange
)添加属性,UIFont
值是您要垂直偏移的值。 NSBaselineOffsetAttributeName
希望这也有助于其他Swift开发者,因为我也需要它。
答案 1 :(得分:11)
作为一种不同的方法,我编写了一个函数,该函数接收一个字符串,其中指数的前缀为^
,例如2^2•3•5^2
并返回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
}
这是一种蛮力方法,但如果您不想处理属性字符串或希望字符串独立于字体,则它可以正常工作。
答案 2 :(得分:10)
我写了以下扩展名,或者你可以将它作为一个函数使用,它对我来说效果很好。您可以通过跳过对您来说不重要的部分来修改它
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}
}
的示例:
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)
答案 3 :(得分:9)
如果您可以使用看起来不完美的文本,只需要一个字符子集就可以使用unicode上标和下标数字:⁰¹³⁴⁵⁶⁷⁸⁹₂₂ ₄₆₇₈₉ 这具有不那么麻烦的优点。
答案 4 :(得分:4)
对于简单易用的Swift解决方案,您可能需要结帐 HandyUIKit 。将其导入项目后(例如通过Carthage - 参见README中的说明),您可以执行以下操作:
import HandyUIKit
"6.022*10^{23}".superscripted(font: UIFont.systemFont(ofSize: 20, weight: .medium))
此行将返回NSAttributedString
,其外观与您要查找的内容完全相同。只需将其分配给UILabel
attributedText
属性,然后即可!
如果您正在寻找下标文字,请改用subscripted(font:)
。它将识别CO_{2}
之类的结构。如果你想组合两者,还有superAndSubscripted(font:)
。
有关更多信息和其他示例,请参阅docs。
答案 5 :(得分:1)
这是一个具有正确错误处理的简单版本,将在游乐场中编译。
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)
答案 6 :(得分:1)
一个很好的简单函数,可以输出数字作为上标文本。
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
}
答案 7 :(得分:1)
在SwiftUI中,可以通过使用baselineOffset修饰符来实现上标效果。例如:
Text("$")
.foregroundColor(Color.white)
.font(.custom(AppTheme.getRegularFont(), size: 13))
.baselineOffset(8.0)
Text("20")
.foregroundColor(AppTheme.primaryColor)
.font(.custom(AppTheme.getRegularFont(), size: 25))
这是它的外观:
答案 8 :(得分:1)
我作为String扩展的解决方案
extension String {
func setAsSuperscript(_ textToSuperscript: String) -> NSMutableAttributedString {
let attributedString = NSMutableAttributedString(string: self)
let foundRange = attributedString.mutableString.range(of: textToSuperscript)
let font = UIFont.systemFont(ofSize: 12)
if foundRange.location != NSNotFound {
attributedString.addAttribute(.font, value: font, range: foundRange)
attributedString.addAttribute(.baselineOffset, value: 3, range: foundRange)
attributedString.addAttribute(.foregroundColor, value: UIColor.red, range: foundRange)
}
return attributedString
}
和用法:
let placeholder = "Required value*".setAsSuperscript("*")
答案 9 :(得分:0)
我创建了一个String扩展,该扩展接受一个字符串并将其所有上标转换为Unicode字符。这样,您可以例如轻松共享结果字符串。
extension Character {
var unicode: String {
// See table here: https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts
let unicodeChars = [Character("0"):"\u{2070}",
Character("1"):"\u{00B9}",
Character("2"):"\u{00B2}",
Character("3"):"\u{00B3}",
Character("4"):"\u{2074}",
Character("5"):"\u{2075}",
Character("6"):"\u{2076}",
Character("7"):"\u{2077}",
Character("8"):"\u{2078}",
Character("9"):"\u{2079}",
Character("i"):"\u{2071}",
Character("+"):"\u{207A}",
Character("-"):"\u{207B}",
Character("="):"\u{207C}",
Character("("):"\u{207D}",
Character(")"):"\u{207E}",
Character("n"):"\u{207F}"]
if let unicode = unicodeChars[self] {
return unicode
}
return String(self)
}
}
extension String {
var unicodeSuperscript: String {
let char = Character(self)
return char.unicode
}
func superscripted() -> String {
let regex = try! NSRegularExpression(pattern: "\\^\\{([^\\}]*)\\}")
var unprocessedString = self
var resultString = String()
while let match = regex.firstMatch(in: unprocessedString, options: .reportCompletion, range: NSRange(location: 0, length: unprocessedString.count)) {
// add substring before match
let substringRange = unprocessedString.index(unprocessedString.startIndex, offsetBy: match.range.location)
let subString = unprocessedString.prefix(upTo: substringRange)
resultString.append(String(subString))
// add match with subscripted style
let capturedSubstring = NSAttributedString(string: unprocessedString).attributedSubstring(from: match.range(at: 1)).mutableCopy() as! NSMutableAttributedString
capturedSubstring.string.forEach { (char) in
let superScript = char.unicode
let string = NSAttributedString(string: superScript)
resultString.append(string.string)
}
// strip off the processed part
unprocessedString.deleteCharactersInRange(range: NSRange(location: 0, length: match.range.location + match.range.length))
}
// add substring after last match
resultString.append(unprocessedString)
return resultString
}
mutating func deleteCharactersInRange(range: NSRange) {
let mutableSelf = NSMutableString(string: self)
mutableSelf.deleteCharacters(in: range)
self = mutableSelf as String
}
}
例如"x^{4+n}+12^{3}".superscripted()
产生"x⁴⁺ⁿ+12³"
这受HandyUIKit的启发,我的代码要旨位于Github
答案 10 :(得分:0)
我创建了一个AmountFormatter类,该类帮助我将十进制数字转换为带有小数点后一位的数字。
class AmountFormatter {
static func sharedFormatter(
decimalNumber: NSDecimalNumber,
currency: String,
raisedDecimals: Bool) -> NSAttributedString {
let numberFormatter = NumberFormatter()
numberFormatter.usesGroupingSeparator = true
numberFormatter.groupingSeparator = "."
numberFormatter.decimalSeparator = ","
numberFormatter.numberStyle = .decimal
let scale: Int16 = 2
let behavior = NSDecimalNumberHandler(
roundingMode: .plain,
scale: scale,
raiseOnExactness: false,
raiseOnOverflow: false,
raiseOnUnderflow: false,
raiseOnDivideByZero: true)
guard let amountString = numberFormatter.string(
from: decimalNumber.rounding(accordingToBehavior: behavior))
else {
fatalError("Can't convert conversion from 'NSDecimalNumber' to string")
}
let currencyAmountString = currency + amountString
let font = UIFont(name: "Roboto", size: 20)
let fontSuper = UIFont(name: "Roboto", size: 10)
let attributedCurrencyAmountString = NSMutableAttributedString(
string: currencyAmountString,
attributes: [.font: font!])
if raisedDecimals == false {
return attributedCurrencyAmountString as NSAttributedString
}
var array = attributedCurrencyAmountString.string.split(separator: ",")
let lenght = array[0].count
attributedCurrencyAmountString.setAttributes(
[.font: fontSuper!, .baselineOffset: 10],
range: NSRange(location: lenght, length: 3))
attributedCurrencyAmountString.setAttributes(
[.font: fontSuper!],
range: NSRange(location: 0, length: 1))
return attributedCurrencyAmountString as NSAttributedString
}
}
答案 11 :(得分:0)
这是使用递归的Swift 5.1解决方案(也应与较早版本的Swift一起使用),该解决方案仅着重于从Int
输出上标(即不显示格式)。
extension Int {
func superscriptString() -> String {
let minusPrefixOrEmpty: String = self < 0 ? Superscript.minus : ""
let (quotient, remainder) = abs(self).quotientAndRemainder(dividingBy: 10)
let quotientString = quotient > 0 ? quotient.superscriptString() : ""
return minusPrefixOrEmpty + quotientString + Superscript.value(remainder)
}
}
enum Superscript {
static let minus = "⁻"
private static let values: [String] = [
"⁰",
"¹",
"²",
"³",
"⁴",
"⁵",
"⁶",
"⁷",
"⁸",
"⁹"
]
static func value(_ int: Int) -> String {
assert(int >= 0 && int <= 9)
return values[int]
}
}
以下是一些证明正确性的测试:
func testPositiveIntegersSuperscript() {
XCTAssertEqual(0.superscriptString(), "⁰")
XCTAssertEqual(1.superscriptString(), "¹")
XCTAssertEqual(2.superscriptString(), "²")
XCTAssertEqual(3.superscriptString(), "³")
XCTAssertEqual(4.superscriptString(), "⁴")
XCTAssertEqual(5.superscriptString(), "⁵")
XCTAssertEqual(6.superscriptString(), "⁶")
XCTAssertEqual(7.superscriptString(), "⁷")
XCTAssertEqual(8.superscriptString(), "⁸")
XCTAssertEqual(9.superscriptString(), "⁹")
XCTAssertEqual(10.superscriptString(), "¹⁰")
XCTAssertEqual(11.superscriptString(), "¹¹")
XCTAssertEqual(12.superscriptString(), "¹²")
XCTAssertEqual(19.superscriptString(), "¹⁹")
XCTAssertEqual(20.superscriptString(), "²⁰")
XCTAssertEqual(21.superscriptString(), "²¹")
XCTAssertEqual(99.superscriptString(), "⁹⁹")
XCTAssertEqual(100.superscriptString(), "¹⁰⁰")
XCTAssertEqual(101.superscriptString(), "¹⁰¹")
XCTAssertEqual(102.superscriptString(), "¹⁰²")
XCTAssertEqual(237.superscriptString(), "²³⁷")
XCTAssertEqual(999.superscriptString(), "⁹⁹⁹")
XCTAssertEqual(1000.superscriptString(), "¹⁰⁰⁰")
XCTAssertEqual(1001.superscriptString(), "¹⁰⁰¹")
XCTAssertEqual(1234.superscriptString(), "¹²³⁴")
XCTAssertEqual(1337.superscriptString(), "¹³³⁷")
}
func testNegativeIntegersSuperscript() {
XCTAssertEqual(Int(-1).superscriptString(), "⁻¹")
XCTAssertEqual(Int(-2).superscriptString(), "⁻²")
XCTAssertEqual(Int(-3).superscriptString(), "⁻³")
XCTAssertEqual(Int(-4).superscriptString(), "⁻⁴")
XCTAssertEqual(Int(-5).superscriptString(), "⁻⁵")
XCTAssertEqual(Int(-6).superscriptString(), "⁻⁶")
XCTAssertEqual(Int(-7).superscriptString(), "⁻⁷")
XCTAssertEqual(Int(-8).superscriptString(), "⁻⁸")
XCTAssertEqual(Int(-9).superscriptString(), "⁻⁹")
XCTAssertEqual(Int(-10).superscriptString(), "⁻¹⁰")
XCTAssertEqual(Int(-11).superscriptString(), "⁻¹¹")
XCTAssertEqual(Int(-12).superscriptString(), "⁻¹²")
XCTAssertEqual(Int(-19).superscriptString(), "⁻¹⁹")
XCTAssertEqual(Int(-20).superscriptString(), "⁻²⁰")
XCTAssertEqual(Int(-21).superscriptString(), "⁻²¹")
XCTAssertEqual(Int(-99).superscriptString(), "⁻⁹⁹")
XCTAssertEqual(Int(-100).superscriptString(), "⁻¹⁰⁰")
XCTAssertEqual(Int(-101).superscriptString(), "⁻¹⁰¹")
XCTAssertEqual(Int(-102).superscriptString(), "⁻¹⁰²")
XCTAssertEqual(Int(-237).superscriptString(), "⁻²³⁷")
XCTAssertEqual(Int(-999).superscriptString(), "⁻⁹⁹⁹")
XCTAssertEqual(Int(-1000).superscriptString(), "⁻¹⁰⁰⁰")
XCTAssertEqual(Int(-1001).superscriptString(), "⁻¹⁰⁰¹")
XCTAssertEqual(Int(-1234).superscriptString(), "⁻¹²³⁴")
XCTAssertEqual(Int(-1337).superscriptString(), "⁻¹³³⁷")
}
由于我的数学和递归技术,我的解决方案的速度是gorillaz' solution(基于字符串和数组)的两倍以上。这是证明:
private typealias SuperscriptVector = (value: Int, expectedSuperstring: String)
private let vector1to9: SuperscriptVector = (123456789, "¹²³⁴⁵⁶⁷⁸⁹")
func performanceTest(times n: Int, function: (Int) -> () -> String) {
func manyTimes(_ times: Int) {
func doTest(vector: SuperscriptVector) {
let result: String = function(vector.value)()
XCTAssertEqual(result, vector.expectedSuperstring)
}
for _ in 0..<times {
doTest(vector: vector1to9)
}
}
manyTimes(n)
}
// 3.244 sec
func testPerformanceMine() {
measure {
performanceTest(times: 1_000_000, function: Int.superscriptString)
}
}
// 7.6 sec
func testPerformanceStackOverflow() {
measure {
performanceTest(times: 1_000_000, function: Int.superscriptStringArrayBased)
}
}
答案 12 :(得分:0)
extension String {
func convertToSuperscriptDigits(from start: Int, to end: Int? = nil) - String {
let end = end ?? self.count
let startIndex = self.index(self.startIndex, offsetBy: start)
let endIndex = self.index(self.startIndex, offsetBy: end)
let replaceRange = startIndex..<endIndex
let substring = self[replaceRange]
let supers = [
"0": "\u{2070}",
"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}"]
let convertString = substring.map { (char) -> Character in
Character(supers[String(char)] ?? String(char))
}
return self.replacingCharacters(in: replaceRange, with: String(convertString))
}
答案 13 :(得分:0)
这将为字符串中的所有数字加上上标,并删除^字符。
使用:
yourstring.addSuper()
代码:
extension String {
func addSuper() -> String {
let charset = CharacterSet(charactersIn: "1234567890")
let toSuper: [Character: String] = ["0": "\u{2070}",
"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}",
"-": "\u{207B}"]
var resultString: String = ""
var index: Int = 0
for charater in self {
if String(charater).rangeOfCharacter(from: charset) != nil {
resultString.append(toSuper[charater] ?? "")
} else if charater != "^" {
resultString.append(charater)
}
index += 1
}
return resultString
}
}
答案 14 :(得分:0)
对于使用SwiftUI的用户,一个选项是在Text()中使用Unicode异常字符串:
<div class="iRow">
<div class="lclass">
<label for="typeselector">Product Category</label>
</div>
<div class="tclass">
<select id="typeselector" name="productoptions">
<option value="DVD">DVD-Disc</option>
<option class="book" value="Book">Book</option>
<option class="furniture" value="Furniture">Furniture</option>
</select>
</div>
</div>
此方法的一个优点是内联sub / supers更加容易。
如果它必须绝对继承自UILabel(例如,用于本机NSAttributedString或本机包装),则可以利用UIViewRepresentable并使用unicode异常字符串(在大多数情况下应该可以使用)。这是SO上的一个选项:Stackoverflow。我还没有尝试答案。
对于那些希望为通用下标和上标(例如算术)使用unicode的人:
上标:
0 = 2070
1 = 00B9
2 = 00B2
3 = 00B3
4 = 2074
5 = 2075
6 = 2076
7 = 2077
8 = 2078
9 = 2079
+ = 207A
-= 207B
(= 207D
)= 207E
n = 207F
下标:
0 = 2080
1 = 2081
2 = 2082
3 = 2083
4 = 2084
5 = 2085
6 = 2086
7 = 2087
8 = 2088
9 = 2089
+ = 208A
-= 208B
(= 208D
)= 208E
e = 2091
n = 2099
参考:unicode.org