在 SwiftUI 中将部分文本加粗
Posted
技术标签:
【中文标题】在 SwiftUI 中将部分文本加粗【英文标题】:Making parts of text bold in SwiftUI 【发布时间】:2020-05-08 03:03:26 【问题描述】:我想知道如何在 SwiftUI 中仅将文本的部分加粗,而将其余部分保持“常规”。
我目前有:
Text("Coronavirus Disease of 2019")
我希望它打印出 COronaVirus Disease of 2019 and have'只能将某些部分加粗。
【问题讨论】:
【参考方案1】:斯威夫特 5.5
Foundation 支持 Markdown。
在要加粗的字符周围添加双星号 (**)。
Text("**CO**rona**V**irus **D**isease of 20**19**")
在要斜体的字符周围添加下划线。
Text("Is this text _emphasized_?")
【讨论】:
实际上,**Bold**
和 __Bold__
都会产生粗体(而 *Italic*
和 _Italic_
会呈现斜体)
应该补充一点,如果字符串由于大小而被分成几部分 ex: Text("Hello there " + "world") 文本将被渲染而没有粗体【参考方案2】:
如果你不需要在这里翻译它是可能的快速变体
Text("CO").bold() + Text("rona") + Text("VI").bold() +
Text("rus Disease of 20") + Text("19").bold()
替代方法是将 NSAttributedString 与 UIViewRepresentable
或 UILabel
一起使用。
【讨论】:
【参考方案3】:添加到 Asperi 的出色答案的快速说明,如果您需要对文本应用框架或填充修饰符,则需要先对文本进行分组,然后将修饰符添加到组中。
Group Text("CO").bold() + Text("rona") + Text("VI").bold() + Text("rus Disease of 20") + Text("19").bold() .frame(width: 100, height: 100).padding(.horizontal)
【讨论】:
【参考方案4】:这个问题出现了很多,对于一个没有 Objective-C 背景的 Swift 新手来说,解决方案是不情愿的。上面的几个答案都很好,但总结一下问题的最佳解决方案,
Group
Text("CO").bold() +
Text("rona") +
Text("V").bold() +
Text("irus ") +
Text("D").bold() +
Text("isease of 20") +
Text("19").bold()
.font(.caption)
.frame(width: 300)
(Group
是我的秘诀)
【讨论】:
【参考方案5】:Swift 5、ios 13
这篇文章是关于改变字符文本的颜色,但你同样可以应用它使用 [a bit mask] 的技术来使某些字符加粗、闪烁、动画等等?
https://medium.com/@marklucking/an-interesting-challenge-with-swiftui-9ebb26e77376
你需要关注的两个核心部分是..
ForEach((0 ..< letter.count), id: \.self) column in
Text(letter[column])
.foregroundColor(colorCode(gate: Int(self.gate), no: column) ? Color.black: Color.red)
.font(Fonts.futuraCondensedMedium(size: fontSize))
还有这个用来掩盖文字的……
func colorCode(gate:Int, no:Int) -> Bool
let bgr = String(gate, radix:2).pad(with: "0", toLength: 16)
let bcr = String(no, radix:2).pad(with: "0", toLength: 16)
let binaryColumn = 1 << no - 1
let value = UInt64(gate) & UInt64(binaryColumn)
let vr = String(value, radix:2).pad(with: "0", toLength: 16)
print("bg ",bgr," bc ",bcr,vr)
return value > 0 ? true:false
【讨论】:
【参考方案6】:@mahan 提出的解决方案很棒,但它有一个限制,即它在 iOS 15 上运行良好,但在 iOS 14 上却不行。
所以我认为对于那些需要支持 iOS 14 的人来说这是一个更好的解决方案,该解决方案是从这个网站复制的: https://www.avanderlee.com/swiftui/text-weight-combinations/
最终代码如下所示:
@main
struct RichTextApp: App
var body: some Scene
WindowGroup
RichText("SwiftLee - A *weekly blog* about Swift, iOS and Xcode *Tips and Tricks*")
.padding()
.multilineTextAlignment(.center)
(您可以自定义字体并在文本中添加变量,例如:)
RichText(" ... *\(viewModel.title)* ...")
代码是:
import SwiftUI
struct RichText: View
struct Element: Identifiable
let id = UUID()
let content: String
let isBold: Bool
init(content: String, isBold: Bool)
var content = content.trimmingCharacters(in: .whitespacesAndNewlines)
if isBold
content = content.replacingOccurrences(of: "*", with: "")
self.content = content
self.isBold = isBold
let elements: [Element]
init(_ content: String)
elements = content.parseRichTextElements()
var body: some View
var content = text(for: elements.first!)
elements.dropFirst().forEach (element) in
content = content + self.text(for: element)
return content
private func text(for element: Element) -> Text
let postfix = shouldAddSpace(for: element) ? " " : ""
if element.isBold
return Text(element.content + postfix)
.fontWeight(.bold)
else
return Text(element.content + postfix)
private func shouldAddSpace(for element: Element) -> Bool
return element.id != elements.last?.id
extension String
/// Parses the input text and returns a collection of rich text elements.
/// Currently supports asterisks only. E.g. "Save *everything* that *inspires* your ideas".
///
/// - Returns: A collection of rich text elements.
func parseRichTextElements() -> [RichText.Element]
let regex = try! NSRegularExpression(pattern: "\\*1(.*?)\\*1")
let range = NSRange(location: 0, length: count)
/// Find all the ranges that match the regex *CONTENT*.
let matches: [NSTextCheckingResult] = regex.matches(in: self, options: [], range: range)
let matchingRanges = matches.compactMap Range<Int>($0.range)
var elements: [RichText.Element] = []
// Add the first range which might be the complete content if no match was found.
// This is the range up until the lowerbound of the first match.
let firstRange = 0..<(matchingRanges.count == 0 ? count : matchingRanges[0].lowerBound)
self[firstRange].components(separatedBy: " ").forEach (word) in
guard !word.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else return
elements.append(RichText.Element(content: String(word), isBold: false))
// Create elements for the remaining words and ranges.
for (index, matchingRange) in matchingRanges.enumerated()
let isLast = matchingRange == matchingRanges.last
// Add an element for the matching range which should be bold.
let matchContent = self[matchingRange]
elements.append(RichText.Element(content: matchContent, isBold: true))
// Add an element for the text in-between the current match and the next match.
let endLocation = isLast ? count : matchingRanges[index + 1].lowerBound
let range = matchingRange.upperBound..<endLocation
self[range].components(separatedBy: " ").forEach (word) in
guard !word.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else return
elements.append(RichText.Element(content: String(word), isBold: false))
return elements
/// - Returns: A string subscript based on the given range.
subscript(range: Range<Int>) -> String
let startIndex = index(self.startIndex, offsetBy: range.lowerBound)
let endIndex = index(self.startIndex, offsetBy: range.upperBound)
return String(self[startIndex..<endIndex])
【讨论】:
这很好,但似乎从文本中删除了新行? @dqualias \n 不适合你?示例“(标题) \n(内容)” 如果我有一个像 "title \n content" 这样的字符串,那么就可以删除换行符。我认为正则表达式正在删除换行符?以上是关于在 SwiftUI 中将部分文本加粗的主要内容,如果未能解决你的问题,请参考以下文章
在 ScrollView 中将文本对齐为前导 - SWIFTUI
如何在 SwiftUI 中将滚动视图添加到屏幕的特定部分? [复制]