2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Swift4】UILabelをコードで生成して位置決めする時に気をつけること

Posted at

忘備録です。
sizeToFit()の仕様で躓いて悩んだので、どういう感じでどう解決するに至ったのか、書いておきます。
 リファレンスにはaddSubViewの後にsizeToFitしろって書いてはありますが、この現象については書いてないですね…。

前提

  • swift4.2,xcode10
  • UILabelをコードで生成
  • 高さ、幅を動的に計算して同じView内に配置
  • UILabelの個数はデータによって変わり、確定していない
  • 配置すると言っても前のものの下に配置する形

やったこと

  • viewDidLoad()で処理
  • sizeToFit()
  • labe.bound.size.heightで高さを取る
  • 変数offsetに+=してy位置を指定する
ViewController.swift

    override func viewDidLoad() {
        super.viewDidLoad()

        (中略

        for nLoop in 0 ... labelTextData.count - 1 {
            let label = UILabel()
            label.numberOfLines = 0
            // ラベルのフォントのオートシュリンクの設定
            label.adjustsFontForContentSizeCategory = true
            label.adjustsFontSizeToFitWidth = true
            label.minimumScaleFactor = 0.3
                    
            // font
            if let customFont = UIFont(name: "Chalkboard SE", size: 17) {
                label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: customFont)
            } else {
                label.font = UIFont.preferredFont(forTextStyle: .body)
            }
            label.text = labelTextData[nLoop].1

            // viewにラベルを追加
            // constraintsよりも前に追加する必要があるらしい
            view.addSubview(label)
            // AutoLayoutとバッティングしないためFalse
            label.translatesAutoresizingMaskIntoConstraints = false
                    
            // constraints
            label.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true
            label.sizeToFit()

            // 大本のViewとX軸中心合わせ
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            // Top Anchorは大本のViewに合わせる(オフセットでずらす。)
            label.topAnchor.constraint(equalTo: view.topAnchor, constant: offset).isActive = true
   
            offset += label.bounds.size.height
        }
    }

結果

  • ラベルの内容は表示されるがheightで取れる値が合わずに重なる
  • ラベルの内容によってずれる高さは変わってくる

迷走

  • UIImageViewに画像突っ込んだらどうなるの?と試して爆死
    • CGRectでUIImageViewを設定したら…駄目
    • Constraintsの設定?…違う
    • UIImageをリサイズしてサイズを確定、Viewも同じサイズで成功
  • Contsraintsの問題?違うっぽい
  • sizeToFit()の位置の問題?元から位置はあってそう
    • text,font等を設定してからsizeToFit()でOK
  • もうめんどくさいオフセットの値に足したれ!
    • 当たり前だけどもきれいには行かない
    • やっぱりちゃんと値を取れるようになろう…。
  • UIImageの時のように先に大きさを指定したらどうかな
    • frameにCGRectでサイズ指定は可能
    • InterfaceBuilderだと先に小さいのが出てくるから小さく…駄目
    • 大きくするにしても横幅は決まってるから、高さを大きく…成功

結論

  • label.frameにCGRectで先に矩形を指定し、その後sizeToFit()
    • heightの値を中に入るテキストよりも絶対に大きくなるように設定
    // 一度大きく高さを設定してからSizetofitで小さく収めないと正確な値が出てこない
    label.frame = CGRect(x: 0 ,y: offset, width: screenWidth * 0.8, height: sceenHeight * 10)

まさかこんな仕様が隠れていたとは…。
会社とかで複数人でやってるならばうまくいかないとか話してれば情報共有で知ってる人からすぐ教えてもらえるケースな気がします。

2
3
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
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?