iOS
tips
UILabel
UIKit
adventcalendar2018

iOSのUILabelのサイズそのままでHiragino SansのqyjpやÉの上下が見切れないようにする


課題

動作環境: iOS10〜12

UILabelのHiragino Sansを直接指定して【英語のみ】とかの場合、下記のようにqyjpやÉの上下が見切れたりします。

スクリーンショット 2018-12-03 18.42.45.png

label.font = UIFont(name: "HiraginoSans-W3", size: fontSize)!

label.text = "Font TestgpÉ"

【AutoLayoutやsizeThatFits()上のサイズを変更することなく】、描画領域を広げて下記みたいにしたい

スクリーンショット 2018-12-03 18.41.51.png


対応方法

上下にgutter(スペース)を確保して、描画領域を広げることで対応。

AutoLayout上のサイズを変更しないためにはalignmentRectInsetsを使用する

import UIKit

class VerticalGutterLabel: UILabel {

/// フォントサイズの1/6のgutterを計算
private var verticalGutter: CGFloat {
guard let font = self.font else {
return 4.0 //font未指定の時の値。だいたい4.0確保しておけばOKなのでそうしておく
}
return ceil(font.pointSize / 6.0)
}

/// サイズ(描画領域)を大きくする
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
size.height += verticalGutter * 2
return size
}

/// 描画領域を大きくした分、描画位置を調整
override func drawText(in rect: CGRect) {
super.drawText(in: UIEdgeInsetsInsetRect(rect, UIEdgeInsets(top: verticalGutter,
left: 0.0,
bottom: verticalGutter,
right: 0.0)))
}

/// 描画領域を大きくした分の部分をAutoLayout上で加算されないように相殺する処理
override var alignmentRectInsets: UIEdgeInsets {
let alignmentRectInsets = super.alignmentRectInsets
return UIEdgeInsets(top: alignmentRectInsets.top + verticalGutter,
left: alignmentRectInsets.left,
bottom: alignmentRectInsets.bottom + verticalGutter,
right: alignmentRectInsets.right)
}

/// alignmentRectInsetsの影響でsizeThatFits(sizeToFit含む)が小さくなってしまうのを相殺する処理
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
size.height += verticalGutter * 2
return size
}
}

修正内容の説明はVerticalGutterLabelのコメント参照

参考にした情報

https://stackoverflow.com/questions/20985085/uilabel-clipping-italic-oblique-text-at-left-and-right-edges-of-content-ios


対応時の注意!!

描画領域を広げているのでbackgroundColorなどの描画領域も広がっているので注意!!

スクリーンショット 2018-12-03 15.52.09.png


"HiraginoSans"で直接指定する理由

Zeplinというツールをデザイン指示に使用しているのですが、

Zeplinで指定するフォントサイズをそのまま設定しても

システムフォント(systemFont(ofSize:)boldSystemFont(ofSize:))だと小さくなってしまうという問題があったためです。

Zeplinでのフォントサイズと"HiraginoSans"直接指定の時のフォントサイズが一致していたため"HiraginoSans"直接指定しています。

よくわかっていないですが、システムフォント指定の場合は"HiraginoSans"の本来のフォントサイズより小さく表示しているのかな。。と思っています。


次の記事は

明日、食べログAdventCalendar11日目は @itume さんからの「POROと大人になった僕」です。