プログラミング

【Swift】UILabelの行間を変更する

swift-eyecatch

iOSアプリ開発で日本語の文言を表示すると、なんか行間が詰まってて微妙だなと感じるときがあります。行間を設定すればよいのですが、なんだかんだ面倒だったりするので、UILabelを継承するAppNameLabelのようなサブクラスを使いまわしたりします。

サブクラスの話はおいておいて、今回はまずはUILabelの行間を設定する方法を記載します。

UILabelに行間を設定するには、attributedTextを使用する必要がある

UILabelにテキストを表示するときは、以下のようなコードを書きます。

label.text = "表示したいテキスト"

UILabelには、様々なパラメータがあります。例えば、行数を複数行にするには、numberOfLinesに0や特定の1以外の数値を設定します。

ただこれだと、行間を設定することが出来ません。

行間を設定するには、attributedTextNSAttributedStringを設定する必要があります。

サンプルコード

import UIKit

class ViewController: UIViewController {

    let text = "テストの文章です。テストの文章です。テストの文章です。テストの文章です。テストの文章です。テストの文章です。テストの文章です。"

    // 行間を調整していないUILabel
    fileprivate lazy var normalLabel: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 14, weight: .regular)
        label.numberOfLines = 0
        label.textAlignment = .center
        label.text = text
        return label
    }()

    // 行間調整済みのUILabel
    fileprivate lazy var lineHeightLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        let style = NSMutableParagraphStyle()
        style.lineSpacing = 20
        style.alignment = .center
        let attributes: [NSAttributedString.Key : Any] = [
            .font : UIFont.systemFont(ofSize: 14, weight: .regular),
            .paragraphStyle: style,
        ]
        label.attributedText = NSAttributedString(string: text, attributes: attributes)
        return label
    }()

    fileprivate lazy var stackView: UIStackView = {
        let stackView = UIStackView()
        stackView.alignment = .center
        stackView.axis = .horizontal
        stackView.spacing = 20
        stackView.addArrangedSubview(normalLabel)
        stackView.addArrangedSubview(lineHeightLabel)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        return stackView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(stackView)
        [stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
         stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
         normalLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.4),
         lineHeightLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.4),]
            .forEach { $0.isActive = true }
    }
}