2
1

More than 3 years have passed since last update.

AutoLayout で表のようなレイアウトをする

Last updated at Posted at 2020-09-02

やりたいこと

こういう↓ View を組みたいとき
capture.png

  • table タグを使ってできるレイアウトのようなもの
  • 左のラベルは右寄せ。それぞれの幅は一番幅が長いものに合わせる
  • 右のラベルは複数行入る。縦方向のレイアウトはこちらで決まる

実現方法

この要件だと UIStackView だけだと実現できなかったので、AutoLayout でゴリッとやったらできた
(Cartography と Then を使っているけど雰囲気は伝わるはず……)

let content: [(heading: String, body: String)] = [
    ("いち: ", "改行\nする\nテキスト"),
    ("に: ", "普通のテキスト"),
    ("さぁん: ", "長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト長いテキスト")
]
let spacing = CGFloat(4)

var prev: (heading: UIView, body: UIView)?
content.forEach { heading, body in
    let headingLabel = UILabel().then {
        $0.text = heading
        table.addSubview($0)
    }
    let bodyLabel = UILabel().then {
        $0.numberOfLines = 0
        $0.text = body
        table.addSubview($0)
    }

    if let (prevHeading, prevBody) = prev {
        constrain(headingLabel, bodyLabel, prevHeading, prevBody) { headingLabel, bodyLabel, prevHeading, prevBody in
            headingLabel.leading >= headingLabel.sv.leading
            headingLabel.top == bodyLabel.top
            headingLabel.trailing == prevHeading.trailing

            bodyLabel.leading == headingLabel.trailing
            bodyLabel.trailing == bodyLabel.sv.trailing
            bodyLabel.top == prevBody.bottom + spacing
        }
    } else {
        constrain(headingLabel, bodyLabel) { headingLabel, bodyLabel in
            headingLabel.leading >= headingLabel.sv.leading
            headingLabel.top == bodyLabel.top

            bodyLabel.leading == headingLabel.trailing
            bodyLabel.trailing == bodyLabel.sv.trailing
            bodyLabel.top == bodyLabel.sv.top
        }
    }

    prev = (headingLabel, bodyLabel)
}
if let (_, prevBody) = prev {
    constrain(prevBody) { prevBody in
        prevBody.bottom == prevBody.sv.bottom
    }
}

みどころ

  • headingLabel.leading >= headingLabel.sv.leading と定義している
  • 横方向は heading が、縦方向は body が決めているので錯綜感がある

misc

他に良い方法あれば教えてください
(左のラベルが固定だったら NSMutableParagraphStyle#headIndent を使うことで、単一の UILabel で実現できるのだけれども)

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1