gpt4 book ai didi

ios - NSAttributedString 在文本和背景前后带有填充

转载 作者:行者123 更新时间:2023-11-28 23:29:25 26 4
gpt4 key购买 nike

我想使用 NSAttributedString 设置文本样式。文本应该有背景和自定义填充,以便文本到背景边缘有一点空间。

这就是我想要实现的目标:

what I want to achieve

这是我不想实现的目标(第二行的背景不是特定于单词/字符的):

what I don't want to achieve

这是我在 Playground 上尝试过的代码:

let quote = "some text with a lot of other text and \nsome other text."
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .left
let attributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.backgroundColor: UIColor.red,
NSAttributedString.Key.foregroundColor: UIColor.white
]
let attributedQuote = NSAttributedString(string: quote, attributes: attributes)

这就是 Playground 预览呈现的内容:

[![ Playground 预览][3]][3]

文本非常接近背景边缘。有什么办法可以让文本的背景有一些空间给文本吗?我需要一些填充物。我尝试使用 headIndent 但这会将带有背景的文本向右移动,而不仅仅是文本。因此它对填充没有用。

最佳答案

The text should have a background and a custom padding, so that the text has a little bit of space to the background's edge.

我找到的最好的方法是使用 TextKit,它有点麻烦,但它是完全模块化的,并且是为此目的而制作的。
在我看来,在其 draw 方法中绘制矩形不是由 TextView 本身决定的,那是 LayoutManager 的工作。

为了简化复制粘贴工作(Swift 5.1 - iOS 13),项目中使用的所有类在下文中提供。

AppDelegate.swift 存储属性以在应用中的任何位置获取文本。

class AppDelegate: UIResponder, UIApplicationDelegate {

lazy var TextToBeRead: NSAttributedString = {

var text: String
if let filepath = Bundle.main.path(forResource: "TextToBeRead", ofType: "txt") {
do { text = try String(contentsOfFile: filepath) }
catch { text = "E.R.R.O.R." }
} else { text = "N.O.T.H.I.N.G." }

return NSAttributedString(string: text)
}()
}

ViewController.swift ⟹ 全屏只有一个 TextView 。

class ViewController: UIViewController, NSLayoutManagerDelegate {

@IBOutlet weak var myTextView: UITextView!
let textStorage = MyTextStorage()
let layoutManager = MyLayoutManager()

override func viewDidLoad() {
super.viewDidLoad()

self.layoutManager.delegate = self

self.textStorage.addLayoutManager(self.layoutManager)
self.layoutManager.addTextContainer(myTextView.textContainer)

let appDelegate = UIApplication.shared.delegate as? AppDelegate
self.textStorage.replaceCharacters(in: NSRange(location: 0, length: 0),
with: (appDelegate?.TextToBeRead.string)!)
}

func layoutManager(_ layoutManager: NSLayoutManager,
lineSpacingAfterGlyphAt glyphIndex: Int,
withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 20.0 }

func layoutManager(_ layoutManager: NSLayoutManager,
paragraphSpacingAfterGlyphAt glyphIndex: Int,
withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 30.0 }
}

MyTextStorage.swift

class MyTextStorage: NSTextStorage {

var backingStorage: NSMutableAttributedString

override init() {

backingStorage = NSMutableAttributedString()
super.init()
}

required init?(coder: NSCoder) {

backingStorage = NSMutableAttributedString()
super.init(coder: coder)
}

// Overriden GETTERS
override var string: String {
get { return self.backingStorage.string }
}

override func attributes(at location: Int,
effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key : Any] {

return backingStorage.attributes(at: location, effectiveRange: range)
}

// Overriden SETTERS
override func replaceCharacters(in range: NSRange, with str: String) {

backingStorage.replaceCharacters(in: range, with: str)
self.edited(.editedCharacters,
range: range,
changeInLength: str.count - range.length)
}

override func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange) {

backingStorage.setAttributes(attrs, range: range)
self.edited(.editedAttributes,
range: range,
changeInLength: 0)
}
}

MyLayoutManager.swift

import CoreGraphics //Important to draw the rectangles

class MyLayoutManager: NSLayoutManager {

override init() { super.init() }

required init?(coder: NSCoder) { super.init(coder: coder) }

override func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) {
super.drawBackground(forGlyphRange: glyphsToShow, at: origin)

self.enumerateLineFragments(forGlyphRange: glyphsToShow) { (rect, usedRect, textContainer, glyphRange, stop) in

var lineRect = usedRect
lineRect.size.height = 30.0

let currentContext = UIGraphicsGetCurrentContext()
currentContext?.saveGState()

currentContext?.setStrokeColor(UIColor.red.cgColor)
currentContext?.setLineWidth(1.0)
currentContext?.stroke(lineRect)

currentContext?.restoreGState()
}
}
}

...最后是这样的: enter image description here

只有自定义颜色和调整几个参数以适应您的项目,但这是显示 NSAttributedString,在文本和背景前后填充 的基本原理...更多如果需要,不超过 2 行。

关于ios - NSAttributedString 在文本和背景前后带有填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57305483/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com