UILabelの高さを文字数によって動的に変更する


テーマ

UILabelの高さを文字数によって動的に変更します。

経緯

サーバーから取得した文字列をもとに、
UILabelの高さを動的に変える必要がありました。
その時のメモを共有します。

実装手順

  1. UILabelをStoryBoardに配置し、numberOfLinesを0(Storyboard上はLines)に変更する。
  2. UILabelの高さ制約(Constraints)を設定し、ソースコードと関連付ける。
  3. UILabelの高さを取得するextensionを作成する。
  4. 画面サイズとフォントサイズを指定し、高さを取得する。
  5. UILabelの高さを更新する。

それでは、やってみます。

1. UILabelをStoryBoardに配置し、numberOfLinesを0(Storyboard上はLines)に変更する。

この設定を忘れると、1行で表示されます。
(1行で収まらない場合は、「...」で省略される。)

2. UILabelの高さ制約(Constraints)を設定し、ソースコードと関連付ける。

高さ制約は、後で変えるので適当でも大丈夫です。

StoryBoardからOutletでソースコードと関連付けます。

UIViewController.swift
    @IBOutlet weak var heightConstrainsts: NSLayoutConstraint!
    @IBOutlet weak var textLabel: UILabel!

関連付けができたら、制約が下記のような表示に変わります。

3. UILabelの高さを取得するextensionを作成する。

String.swift
import UIKit

extension String {

    func getTextSize(font:UIFont, viewWidth:CGFloat, padding:CGFloat) -> CGSize {
        var size = CGSizeZero

        if let s:CGSize = self.makeSize(viewWidth, font: font) {
            size = CGSize(width: s.width, height: s.height + padding)
        }
        return size
    }

    func makeSize(width:CGFloat, font:UIFont) -> CGSize {        
        var size:CGSize = CGSizeZero

        if self.respondsToSelector("boundingRectWithSize:options:attributes:context:") {
            let bounds:CGSize = CGSize(width: width, height: CGFloat.max)
            let attributes: Dictionary = [NSFontAttributeName: font]
            let options = unsafeBitCast(NSStringDrawingOptions.UsesLineFragmentOrigin.rawValue |
                NSStringDrawingOptions.UsesFontLeading.rawValue, NSStringDrawingOptions.self)

            let rect:CGRect = self.boundingRectWithSize(bounds, options: options, attributes: attributes, context: nil)
            size = CGSize(width: rect.size.width, height: rect.size.height)
        }
        return size
    }
}

4. 画面サイズとフォントサイズを指定し、高さを取得する。

今回は、下記のような例で説明します。

設定要素 設定値
Viewの幅 UILabelの幅を画面サイズの90%
フォントサイズ 17.0
UIViewController.swift
        let viewWidth = UIScreen.mainScreen().bounds.width * 0.9
        let textSize = text.getTextSize(UIFont.systemFontOfSize(17),viewWidth: viewWidth, padding: 8)
        textLabel.text = text

5. UILabelの高さを更新する。

UIViewController.swift
        heightConstrainsts.constant = textSize.height

検証してみます

[3行表示の場合]

[ちょっと長めの文字列を設定した場合]

[改行コードが含まれる文字列を設定した場合]

まとめ

無事、動的にUILabelの高さを変更できました。

誤りやもっと良い方法があれば、ご教授ください。