Wal*_*ter 9 padding nsattributedstring uilabel ios swift
我想使用 来设置文本样式NSAttributedString。文本应该有背景和自定义填充,以便文本到背景边缘有一点空间。
这就是我想要实现的目标:
这是我不想实现的目标(第二行的背景不是特定于单词/字符的):
这是我在操场上尝试过的代码:
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)
Run Code Online (Sandbox Code Playgroud)
这就是游乐场预览呈现的内容:
[![操场预览][3]][3]
文本非常接近背景边缘。有什么办法可以让文本的背景有一些空间给文本吗?我需要一些填充物。我尝试使用headIndent,但这会将文本及其背景移动到右侧,而不仅仅是文本。因此它对于填充没有用处。
\n\n\n文本应该有背景和自定义填充,以便文本到背景边缘有一点空间。
\n
我发现的最好的方法是使用 TextKit,它有点麻烦,但它是完全模块化的,并且是为此目的而设计的。
\n在我看来,在其方法中绘制矩形并不取决于 TextView 本身draw,而是 LayoutManager 的工作。
下面提供了项目中使用的整个类,以便简化复制粘贴工作(Swift 5.1 - iOS 13)。
\n\nAppDelegate.swift存储属性以在应用程序中的任何位置获取文本。
\n\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n lazy var TextToBeRead: NSAttributedString = {\n\n var text: String\n if let filepath = Bundle.main.path(forResource: "TextToBeRead", ofType: "txt") {\n do { text = try String(contentsOfFile: filepath) }\n catch { text = "E.R.R.O.R." }\n } else { text = "N.O.T.H.I.N.G." }\n\n return NSAttributedString(string: text)\n }()\n}\nRun Code Online (Sandbox Code Playgroud)\n\nViewController.swift \xe2\x9f\xb9 全屏时只有一个文本视图。
\n\nclass ViewController: UIViewController, NSLayoutManagerDelegate {\n\n @IBOutlet weak var myTextView: UITextView!\n let textStorage = MyTextStorage()\n let layoutManager = MyLayoutManager()\n\n override func viewDidLoad() {\n super.viewDidLoad()\n\n self.layoutManager.delegate = self\n\n self.textStorage.addLayoutManager(self.layoutManager)\n self.layoutManager.addTextContainer(myTextView.textContainer)\n\n let appDelegate = UIApplication.shared.delegate as? AppDelegate\n self.textStorage.replaceCharacters(in: NSRange(location: 0, length: 0),\n with: (appDelegate?.TextToBeRead.string)!)\n }\n\n func layoutManager(_ layoutManager: NSLayoutManager,\n lineSpacingAfterGlyphAt glyphIndex: Int,\n withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 20.0 }\n\n func layoutManager(_ layoutManager: NSLayoutManager,\n paragraphSpacingAfterGlyphAt glyphIndex: Int,\n withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 30.0 }\n}\nRun Code Online (Sandbox Code Playgroud)\n\nMyTextStorage.swift
\n\nclass MyTextStorage: NSTextStorage {\n\n var backingStorage: NSMutableAttributedString\n\n override init() {\n\n backingStorage = NSMutableAttributedString()\n super.init()\n }\n\n required init?(coder: NSCoder) {\n\n backingStorage = NSMutableAttributedString()\n super.init(coder: coder)\n }\n\n// Overriden GETTERS\n override var string: String {\n get { return self.backingStorage.string }\n }\n\n override func attributes(at location: Int,\n effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key : Any] {\n\n return backingStorage.attributes(at: location, effectiveRange: range)\n }\n\n// Overriden SETTERS\n override func replaceCharacters(in range: NSRange, with str: String) {\n\n backingStorage.replaceCharacters(in: range, with: str)\n self.edited(.editedCharacters,\n range: range,\n changeInLength: str.count - range.length)\n }\n\n override func setAttributes(_ attrs: [NSAttributedString.Key : Any]?, range: NSRange) {\n\n backingStorage.setAttributes(attrs, range: range)\n self.edited(.editedAttributes,\n range: range,\n changeInLength: 0)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\nMyLayoutManager.swift
\n\nimport CoreGraphics //Important to draw the rectangles\n\nclass MyLayoutManager: NSLayoutManager {\n\n override init() { super.init() }\n\n required init?(coder: NSCoder) { super.init(coder: coder) }\n\n override func drawBackground(forGlyphRange glyphsToShow: NSRange, at origin: CGPoint) { \n super.drawBackground(forGlyphRange: glyphsToShow, at: origin)\n\n self.enumerateLineFragments(forGlyphRange: glyphsToShow) { (rect, usedRect, textContainer, glyphRange, stop) in\n\n var lineRect = usedRect\n lineRect.size.height = 30.0\n\n let currentContext = UIGraphicsGetCurrentContext()\n currentContext?.saveGState()\n\n currentContext?.setStrokeColor(UIColor.red.cgColor)\n currentContext?.setLineWidth(1.0)\n currentContext?.stroke(lineRect)\n\n currentContext?.restoreGState()\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n只需自定义颜色并调整一些参数以适应您的项目,但这就是显示NSAttributedString 的基本原理,该字符串在文本和背景之前和之后具有填充......如果需要的话,可以显示超过 2 行。
\n