はじめに

IMG_0243.jpg
☝︎こんな感じの表示をUILabelのattributedTextを使って実現しようとしたら一工夫必要でした。
私はこうやりましたということで、書き留めておきます。

こうやりました

TagTitleLabel.swift
import UIKit

class TagTitleLabel: UILabel {

    let margin: CGFloat = 3
    let tagBackgroundColor = UIColor.black
    let tagTextColor = UIColor.white

    public func tag(_ tag: String, title: String) {
        let tagString = NSMutableAttributedString(string: tag)
        let par = NSMutableParagraphStyle()
        par.lineSpacing = margin // 行間
        par.lineHeightMultiple = (font.pointSize + margin) / font.pointSize // ラベル高さ倍数
        tagString.addAttributes([
            NSAttributedStringKey.backgroundColor: tagBackgroundColor,
            NSAttributedStringKey.foregroundColor: tagTextColor,
            NSAttributedStringKey.paragraphStyle: par,
            NSAttributedStringKey.font: font],
                                     range: NSRange(location: 0, length: tagString.length))
        let titleString = NSMutableAttributedString(string: title)
        titleString.addAttributes([
            NSAttributedStringKey.foregroundColor: textColor,
            NSAttributedStringKey.font: font,
            NSAttributedStringKey.paragraphStyle: par],
                                        range: NSRange(location: 0, length: titleString.length))

        let dummyString = NSMutableAttributedString(string: "\n")
        let dummyPar = NSMutableParagraphStyle()
        dummyPar.maximumLineHeight = 0
        dummyString.addAttributes([
            NSAttributedStringKey.foregroundColor: UIColor.clear,
            NSAttributedStringKey.font: font,
            NSAttributedStringKey.paragraphStyle: dummyPar],
                                  range: NSRange(location: 0, length: dummyString.length))

        let text = NSMutableAttributedString(attributedString: tagString)
        text.append(titleString)
        text.append(dummyString)
        self.attributedText = text
        self.numberOfLines = 0
    }

}

ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let tagTitleLabel = TagTitleLabel(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
        tagTitleLabel.tag("タグ", title: "あああああああああああああああああああああああああああああああああああああああああああああああああああ")
        tagTitleLabel.sizeToFit()
    }
}

工夫箇所

  1. lineHeightMultipleなどで高さを指定しても均等にマージンが取られず、文字の上部分にマージンが取られてしまう。 (これだけだとタグ部分の背景塗りつぶしでバレてしまうため、NG)
  2. lineSpacingは行間の距離。これを二等分にして上下のテキストに割り当てられるため、これを使って足りなかったした部分のマージンを補う。

  3. ただし、二行目以降が存在しないとタグの部分のマージンが取られず終わってしまうため、最後に高さゼロのダミーのテキストを挿入し、マージンだけ利用させていただく。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.