私はSwiftUIをいじっており、プロジェクトにカスタムUIフォントを使用したいと考えています。ただし、組み込みのフォントクラスに付属している動的な型のサイズ変更(大きなタイトルなど)を失いたくありません。
AppleはText
のカスタムフォント修飾子を提供しています:
_Text("Hello, world!")
.font(.custom("Papyrus", size: 17))
_
ただし、これによりサイズが17ptに固定されます。これをデバイスまたはシミュレーターで実行し、アクセシビリティインスペクターを開いてOSレベルのフォントサイズを調整しても、Text
要素は更新されません。
_size:
_パラメータはオプションではないため、何かを渡す必要があります。残念ながら、size
にはFont
パラメータがないため、既存のフォントのsize
を取得することはできません(カスタムフォントであっても)。
残りのSwiftUIの一般的なパターンのように、パラメーターはオプションにすることも、nil
を渡して特定の動作を明示的に無効にすることもできます。 .custom()
の_size:
_パラメータはオプションであり、内部では以前のFont
修飾子のサイズを使用するか、Text
。
または、システムスタイルを定義する静的メソッド(_.largeTitle
_など)は、カスタムフォント名を提供する引数を受け入れることができます:.largeTitle("Papyrus")
誰か回避策はありますか?
ViewModifier
でもこれを実現するための良い方法を見つけました。動的タイプとカスタムフォントについて、ベース修飾子を このHacking With Swiftの記事 から借りました。結果は次のとおりです。
import SwiftUI
@available(iOS 13, macCatalyst 13, tvOS 13, watchOS 6, *)
struct CustomFont: ViewModifier {
@Environment(\.sizeCategory) var sizeCategory
var name: String
var style: UIFont.TextStyle
var weight: Font.Weight = .regular
func body(content: Content) -> some View {
return content.font(Font.custom(
name,
size: UIFont.preferredFont(forTextStyle: style).pointSize)
.weight(weight))
}
}
@available(iOS 13, macCatalyst 13, tvOS 13, watchOS 6, *)
extension View {
func customFont(
name: String,
style: UIFont.TextStyle,
weight: Font.Weight = .regular) -> some View {
return self.modifier(CustomFont(name: name, style: style, weight: weight))
}
}
そして使い方:
Text("Hello World!")
.customFont(name: "Georgia", style: .headline, weight: .bold)
このようにして、明示的にサイズを指定する必要なく、バンドルされたテキストスタイルに固執できます。そうしたい場合は、font
修飾子を使用してすでに許可されており、スケーリングは、この質問に与えられた代替アプローチの1つを使用して処理できます。
また、スタイルはViewModifier
準拠struct
内に適用され、環境のsizeCategory
への変更に応答するため、ビューにはアクセシビリティへの変更が反映されることに注意してください。アプリに切り替えた直後の設定。したがって、再起動する必要はありません。
私が行う方法は、環境のサイズカテゴリの変更にバインドできるカスタム修飾子を作成することです。
Papyrusを使用する必要があるときはいつでも、次のように使用します。
Text("Hello World!").modifier(Papyrus())
またはこのように:
Text("Hello World!").modifier(Papyrus(.caption))
Text("Hello World!").modifier(Papyrus(.footnote))
Text("Hello World!").modifier(Papyrus(.subheadline))
Text("Hello World!").modifier(Papyrus(.callout))
Text("Hello World!").modifier(Papyrus())
Text("Hello World!").modifier(Papyrus(.body))
Text("Hello World!").modifier(Papyrus(.headline))
Text("Hello World!").modifier(Papyrus(.title))
Text("Hello World!").modifier(Papyrus(.largeTitle))
これでテキストは動的に変化し、追加の作業は必要ありません。これは同じコードで、異なるテキストサイズ設定に反応します。
そして、Papyrus()の実装は次のようになります。各カテゴリの適切な値を把握する必要があります。これは単なる例です。
struct Papyrus: ViewModifier {
@Environment(\.sizeCategory) var sizeCategory
var textStyle: Font.TextStyle
init(_ textStyle: Font.TextStyle = .body) {
self.textStyle = textStyle
}
func body(content: Content) -> some View {
content.font(getFont())
}
func getFont() -> Font {
switch(sizeCategory) {
case .extraSmall:
return Font.custom("Papyrus", size: 16 * getStyleFactor())
case .small:
return Font.custom("Papyrus", size: 21 * getStyleFactor())
case .medium:
return Font.custom("Papyrus", size: 24 * getStyleFactor())
case .large:
return Font.custom("Papyrus", size: 28 * getStyleFactor())
case .extraLarge:
return Font.custom("Papyrus", size: 32 * getStyleFactor())
case .extraExtraLarge:
return Font.custom("Papyrus", size: 36 * getStyleFactor())
case .extraExtraExtraLarge:
return Font.custom("Papyrus", size: 40 * getStyleFactor())
case .accessibilityMedium:
return Font.custom("Papyrus", size: 48 * getStyleFactor())
case .accessibilityLarge:
return Font.custom("Papyrus", size: 52 * getStyleFactor())
case .accessibilityExtraLarge:
return Font.custom("Papyrus", size: 60 * getStyleFactor())
case .accessibilityExtraExtraLarge:
return Font.custom("Papyrus", size: 66 * getStyleFactor())
case .accessibilityExtraExtraExtraLarge:
return Font.custom("Papyrus", size: 72 * getStyleFactor())
@unknown default:
return Font.custom("Papyrus", size: 36 * getStyleFactor())
}
}
func getStyleFactor() -> CGFloat {
switch textStyle {
case .caption:
return 0.6
case .footnote:
return 0.7
case .subheadline:
return 0.8
case .callout:
return 0.9
case .body:
return 1.0
case .headline:
return 1.2
case .title:
return 1.5
case .largeTitle:
return 2.0
@unknown default:
return 1.0
}
}
}
[〜#〜]更新[〜#〜]
テキストスタイルをパラメーターとして受け入れるように実装を変更しました。
SwiftUIのようなスタイルを維持したい場合は、UIKit互換プラットフォーム用にFont
を拡張できます。
_import SwiftUI
extension Font {
#if canImport(UIKit)
static var myHeadline = Font.custom(
"Your-Font-Name",
size: UIFontMetrics(forTextStyle: .headline).scaledValue(for: 17)
)
#endif
}
_
次に、それを使用するには:
_Text("Hello World!")
.font(.myHeadline)
_
アプリケーションを再起動しない限り、カスタムフォントは更新されないことに注意してください。つまり、キャンバスプレビューはこの方法でも機能しません。
時間があれば、このトピックをさらに調査します。
(また、これはネイティブ機能である必要があります。Font.system(_ style: Font.TextStyle, design: Font.Design = .default)
がある場合は、Font.custom(_ name: String, style: Font.TextStyle)
も必要です。フィードバックのFB6523689を参照してください。)