文系プログラマの勉強ノート

スマホアプリ開発やデザインなどについて勉強したことをまとめています

【Xcode】UILabelの文字サイズを自動調整する

画面サイズに合わせてUILabelが拡大縮小する場合に、文字サイズも自動調整する方法。

何もしないとどうなるか

サンプルとして、5.5inch(ex. iPhone8 Plus)の画面サイズに合わせてレイアウトを作成しました。
青い四角部分がUILabelで、画面サイズに合わせてサイズが変わります。

まず iPhone8 Plusで表示した場合。問題ありません。
f:id:an3714106:20171129235157p:plain

次にiPhone4sで表示した場合。文字が省略されてしまいました。
これを調整していきます。
f:id:an3714106:20171129235212p:plain

1. Autoshrinkを有効にする

UILabelにはAutoshrinkという、UILabelのサイズに合わせて文字サイズを自動調整してくれるそのものずばりな機能があります。

Storyboardから設定する場合。
「Autoshrink」を「Minimum Font Scale」にし、下の欄でScaleを指定します。
Scaleは、自動調整時の文字サイズ最小値を、元々の文字サイズに対する比率で入力します。
f:id:an3714106:20171129235540p:plain

コードから設定する場合。

label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.3

f:id:an3714106:20171130000401p:plain

文字サイズが自動調整されました。
ただ、これだとラベルぎりぎりすぎるので、余白をつけたい場合は次に進みます。

2. drawTextで余白(padding)を付ける

UILabelのカスタムクラスを作成し、下記のようにdrawTextを実装します。

class AutoShrinkLabel: UILabel {
    
    var padding: UIEdgeInsets = UIEdgeInsetsMake(4, 4, 4, 4)

    override func drawText(in rect: CGRect) {
        let newRect = UIEdgeInsetsInsetRect(rect, padding)
        super.drawText(in: newRect)
    }
}

Storyboardからラベルに設定します。
f:id:an3714106:20171203230006p:plain

余白がつきました。
f:id:an3714106:20171203231831p:plain

大体これでいけるのですが、この方法は縦方向に余白を大きく取りたい場合に上手くいかないことがあります。
おそらく「label.adjustsFontSizeToFitWidth」というプロパティ名の通り、幅に合わせて自動調整しているため。

3. viewDidLayoutSubviewsで余白(padding)を付ける

drawTextでは調整しきれない場合は、UIViewControllerでviewDidLayoutSubviewsを実装して自力で計算します。
こうなるとdrawTextはなくてもいいかも。

class AutoShrinkLabel: UILabel {   
    var padding: UIEdgeInsets = UIEdgeInsetsMake(20, 4, 20, 4)
}

class ViewController: UIViewController {

    @IBOutlet weak var label: AutoShrinkLabel!
    
    override func viewDidLayoutSubviews() {
        let fontSize = label.frame.size.height - (label.padding.top + label.padding.bottom)
        label.font = label.font.withSize(fontSize)
    }
}

f:id:an3714106:20171203234559p:plain

以上です!