こんにちは、餅屋です!
最近SwiftUIで趣味のアプリ開発をしています。
普段はUIデザイナーをしているので、思った通りの見た目をコードで実現しようと奮闘中。
今回は、Text表示で、でシステムフォント(SanFransisco)が等幅にできないという壁にぶちたりました。
↓こんなかんじになってしまう。
その解決方法がわかったので、共有したいと思います。
目次
等幅フォントとは
多くのフォントは、プロポーショナルフォントといって字ごとに文字幅が違います。
逆に、どんな字でも同じ文字幅をとっているのは等幅フォントと呼ばれます。
iOSでデフォルトで使用されるフォント、Sanfransiscoは、プロポーショナルフォント。
例えば、SFフォントで1と8をそれぞれ10文字表示させてみます。
同じ10文字でも、だいぶ横幅が違いますね。
文章で使う文にはこれで良いのですが、UIとして実装しようとすると不都合が起こる場合があります。
カウントダウンを実装したとき、↓のようになってしまいました。
機能としては問題ないのですが、文字ががぴょこぴょこ動いて気持ち悪いです。
解決方法
最初に結論から。
TextにSFフォントを等幅で表示したい場合は、下記のようにすれば解決です。
Text("等幅フォントにしたい文字").font(Font(UIFont.monospacedDigitSystemFont(ofSize: 50, weight: .light)))
ofSizeとweightは好きなものを選んでください。
コピペで試せるサンプルは↓
import SwiftUI
struct ContentView: View {
var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
@State var duration: Int = 99
var body: some View {
HStack(alignment:.bottom){
Text("\(self.duration)")
.font(Font(UIFont.monospacedDigitSystemFont(ofSize: 60, weight: .light)))//←コレ
Text("秒")
.font(.system(size: 30))
.offset(y: -9)
}.onReceive(timer, perform: { _ in
self.duration -= 1
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
実行結果
ずっと表示させると負の値をとりますが、サンプルなので気にしない
終わりに
余談ですが、SwiftUIで等幅フォントの表示を調べると、たいてい↓
Text("文字列").font(.system(フォントサイズ, design: .monospace))
というふうに、designで.monosupaceを指定するとなっています。
ただこれ、確かに等幅にはなるのですがフォントの形がぜんぜん違うんですよね。
この等幅フォントは、「SF Mono」というもので、システムフォントの「SF」とは別物。
正確には、システムフォントののSFもいろいろなものがあるけど
「SF Mono」はコードエディタなどに使うことを想定されているので、ちょっと癖が強い気がします。
特に1と0。
そんな感じで、SFフォントを等幅に表示させるだけで結構調べたので、今回記事にしました。
ご参考になったら幸い!