首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在带有背景颜色的UILabel中添加填充

在带有背景颜色的UILabel中添加填充
EN

Stack Overflow用户
提问于 2021-01-05 16:20:25
回答 3查看 789关注 0票数 1

我有一个多行UILabel,其中包含一个NSAttributedString,这有一个背景颜色,以提供上述效果。

这很好,但我需要在标签中填充,以便在左边留出一点空间。还有其他关于如何解决这个问题的文章,例如通过子类UILabel来添加UIEdgeInsets。然而,这仅仅是为我添加了标签的外部填充。

关于如何将填充物添加到这个标签上,有什么建议吗?

编辑:抱歉,如果这让人困惑,但最终的目标是这样的……

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-12 14:52:40

根据这里提供的答案:https://stackoverflow.com/a/59216224/6257435

只是为了演示(几个硬编码值,理想情况下是动态/计算的):

代码语言:javascript
运行
复制
class ViewController: UIViewController, NSLayoutManagerDelegate {
    
    var myTextView: UITextView!
    let textStorage = MyTextStorage()
    let layoutManager = MyLayoutManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        myTextView = UITextView()
        myTextView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(myTextView)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            myTextView.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            myTextView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            myTextView.widthAnchor.constraint(equalToConstant: 248.0),
            myTextView.heightAnchor.constraint(equalToConstant: 300.0),
        ])
    
        self.layoutManager.delegate = self
        
        self.textStorage.addLayoutManager(self.layoutManager)
        self.layoutManager.addTextContainer(myTextView.textContainer)
        
        let quote = "This is just some sample text to demonstrate the word wrapping with padding at the beginning (leading) and ending (trailing) of the lines of text."
        self.textStorage.replaceCharacters(in: NSRange(location: 0, length: 0), with: quote)
        
        guard let font = UIFont(name: "TimesNewRomanPSMT", size: 24.0) else {
            fatalError("Could not instantiate font!")
        }
        let attributes: [NSAttributedString.Key : Any] = [NSAttributedString.Key.font: font]
        self.textStorage.setAttributes(attributes, range: NSRange(location: 0, length: quote.count))

        myTextView.isUserInteractionEnabled = false
        
        // so we can see the frame of the textView
        myTextView.backgroundColor = .systemTeal
    }
    
    func layoutManager(_ layoutManager: NSLayoutManager,
                       lineSpacingAfterGlyphAt glyphIndex: Int,
                       withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 14.0 }
    
    func layoutManager(_ layoutManager: NSLayoutManager,
                       paragraphSpacingAfterGlyphAt glyphIndex: Int,
                       withProposedLineFragmentRect rect: CGRect) -> CGFloat { return 14.0 }
}

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)
    }
}

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 = 41.0
            
            let currentContext = UIGraphicsGetCurrentContext()
            currentContext?.saveGState()
            
            // outline rectangles
            //currentContext?.setStrokeColor(UIColor.red.cgColor)
            //currentContext?.setLineWidth(1.0)
            //currentContext?.stroke(lineRect)

            // filled rectangles
            currentContext?.setFillColor(UIColor.orange.cgColor)
            currentContext?.fill(lineRect)

            currentContext?.restoreGState()
        }
    }
}

输出(teal-后台显示框架):

票数 1
EN

Stack Overflow用户

发布于 2021-01-05 16:51:20

我用了一种不同的方式。首先,我从UILabel中获取所有行,并在每一行的起始位置添加额外的空白。要从UILabel中获取所有行,我只需修改此链接(https://stackoverflow.com/a/55156954/14733292)中的代码即可。

最终的extension UILabel代码:

代码语言:javascript
运行
复制
extension UILabel {
    var addWhiteSpace: String {
        guard let text = text, let font = font else { return "" }
        let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
        let attStr = NSMutableAttributedString(string: text)
        attStr.addAttribute(kCTFontAttributeName as NSAttributedString.Key, value: ctFont, range: NSRange(location: 0, length: attStr.length))
        let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
        let path = CGMutablePath()
        path.addRect(CGRect(x: 0, y: 0, width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), transform: .identity)
        let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
        guard let lines = CTFrameGetLines(frame) as? [Any] else { return "" }
        
        return lines.map { line in
            let lineRef = line as! CTLine
            let lineRange: CFRange = CTLineGetStringRange(lineRef)
            let range = NSRange(location: lineRange.location, length: lineRange.length)
            return "  " + (text as NSString).substring(with: range)
        }.joined(separator: "\n")
    }
}

使用:

代码语言:javascript
运行
复制
let labelText = yourLabel.addWhiteSpace
let attributedString = NSMutableAttributedString(string: labelText)
attributedString.addAttribute(NSAttributedString.Key.backgroundColor, value: UIColor.red, range: NSRange(location: 0, length: labelText.count))
yourLabel.attributedText = attributedString
yourLabel.backgroundColor = .yellow

编辑:

上面的代码在某种程度上是可以工作的,但这还不够。因此,我创建了一个类,添加了填充和一个形状调整层。

代码语言:javascript
运行
复制
class AttributedPaddingLabel: UILabel {
    
    private let leftShapeLayer = CAShapeLayer()
    
    var leftPadding: CGFloat = 5
    var attributedTextColor: UIColor = .red
    
    override func awakeFromNib() {
        super.awakeFromNib()
        self.addLeftSpaceLayer()
        self.addAttributed()
    }
    
    override func drawText(in rect: CGRect) {
        let insets = UIEdgeInsets(top: 0, left: leftPadding, bottom: 0, right: 0)
        super.drawText(in: rect.inset(by: insets))
    }
    
    override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + leftPadding, height: size.height)
    }
    
    override var bounds: CGRect {
        didSet {
            preferredMaxLayoutWidth = bounds.width - leftPadding
        }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        leftShapeLayer.path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: leftPadding, height: rect.height)).cgPath
    }
    
    private func addLeftSpaceLayer() {
        leftShapeLayer.fillColor = attributedTextColor.cgColor
        self.layer.addSublayer(leftShapeLayer)
    }
    
    private func addAttributed() {
        let lblText = self.text ?? ""
        let attributedString = NSMutableAttributedString(string: lblText)
        attributedString.addAttribute(NSAttributedString.Key.backgroundColor, value: attributedTextColor, range: NSRange(location: 0, length: lblText.count))
        self.attributedText = attributedString
    }
}

使用方法:

代码语言:javascript
运行
复制
class ViewController: UIViewController {
    
    @IBOutlet weak var lblText: AttributedPaddingLabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        lblText.attributedTextColor = .green
        lblText.leftPadding = 10
        
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-01-14 23:36:44

SwiftUI

这只是SwiftUI中的一个建议。我希望这将是有用的。

步骤1:创建内容

代码语言:javascript
运行
复制
let string =
"""
Lorem ipsum
dolor sit amet,
consectetur
adipiscing elit.
"""

步骤2:应用属性

代码语言:javascript
运行
复制
let attributed: NSMutableAttributedString = .init(string: string)
attributed.addAttribute(.backgroundColor, value: UIColor.orange, range: NSRange(location: 0, length: attributed.length))
attributed.addAttribute(.font, value: UIFont(name: "Times New Roman", size: 22)!, range: NSRange(location: 0, length: attributed.length))

步骤3:使用AttributedLabel ()在SwiftUI中创建UILabel

代码语言:javascript
运行
复制
struct AttributedLabel: UIViewRepresentable {
    let attributedString: NSAttributedString
    
    func makeUIView(context: Context) -> UILabel {
        let label = UILabel()
        label.lineBreakMode = .byClipping
        label.numberOfLines = 0

        return label
    }
    
    func updateUIView(_ uiView: UILabel, context: Context) {
        uiView.attributedText = attributedString
    }
}

最后一步:使用它并添加.padding()

代码语言:javascript
运行
复制
struct ContentView: View {
    var body: some View {
        AttributedLabel(attributedString: attributed)
            .padding()
    }
}

其结果是:

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65582672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档