お題
- このような名札.pngの上にユーザーが入力したテキストを配置するにはどうすれば良いか
- 画像のサイズは可変とする
実装のコツ
AutoLayoutの Multiplier
を使うことで、画像サイズからパーセント指定で位置を指定することができます
指定の仕方
まず配置するUILabelの準備
- 名札からはみ出さないように、幅に合わせてfontサイズを調整してくれる
adjustsFontSizeToFitWidth
をtrue
に -
minimumScaleFactor
で最小フォントサイズを指定します
var nameLabel: UILabel = {
let lb = UILabel()
lb.text = "きんにくひろし"
lb.numberOfLines = 1
lb.font = UIFont.boldSystemFont(ofSize: 48)
lb.adjustsFontSizeToFitWidth = true
lb.minimumScaleFactor = 8 / lb.font.pointSize
return lb
}()
AutoLayoutの指定
translatesAutoresizingMaskIntoConstraints
を false
に
NSLayoutConstraint
を使ってLayoutします
multiplier
を使うことで、パーセント指定で親要素からの相対的な位置を指定することができます。
※この際、left margin
なら親要素の right margin
を対象にすることで、指定が効きます。
left margin
を対象に指定してしまうと、起点0なので思うようにレイアウトが効きません。
※上下左右マージンを指定しないと、テキストがadjustしてくれません
nameLabel.translatesAutoresizingMaskIntoConstraints = false
// 名前LabelのAutoLayout
imageView.addConstraints([
// top
NSLayoutConstraint(
item: nameLabel,
attribute: .top,
relatedBy: .equal,
toItem: imageView,
attribute: .bottom,
multiplier: 0.65,
constant: 0
),
// bottom
NSLayoutConstraint(
item: nameLabel,
attribute: .bottom,
relatedBy: .equal,
toItem: imageView,
attribute: .bottom,
multiplier: 0.85,
constant: 0
),
// left
NSLayoutConstraint(
item: nameLabel,
attribute: .left,
relatedBy: .equal,
toItem: imageView,
attribute: .right,
multiplier: 0.23,
constant: 0
),
// right
NSLayoutConstraint(
item: nameLabel,
attribute: .right,
relatedBy: .equal,
toItem: imageView,
attribute: .right,
multiplier: 0.7,
constant: 0
)
])
完成
ベースの画像サイズが可変しても、綺麗にテキストが収まっています
CustomViewにしておくと、複数画面で利用するとき便利でしょう
Landscape | Portrait |
---|---|
![]() |
![]() |
Multiplierの値をどう決めるか?
Zeplinで簡単に取れます。
Alt
を押しながら確認したいmarginあたりにカーソルを近づけると親要素からの
marginを%表示できるので、それを使います。

(Sketchでもできるかも..少し触っただけだと%表示できなかった)
おまけ:SnapKitを使った実装
41行 -> 6行で書けました 便利
// 名前LabelのAutoLayout
nameLabel.snp.makeConstraints { (make) in
make.top.equalTo(imageView.snp.bottom).multipliedBy(0.65)
make.bottom.equalTo(imageView.snp.bottom).multipliedBy(0.85)
make.left.equalTo(imageView.snp.right).multipliedBy(0.23)
make.right.equalTo(imageView.snp.right).multipliedBy(0.7)
}