忽略动态类型时,在SwiftUI iOS 13+中固定自定义字体的大小

19

我正在开发的应用程序中(适用于iOS13及以上版本的SwiftUI),我导入了自定义字体,并使用以下方法加载该字体:

func getDigitalXFontOfSize(size s : CGFloat) -> Font {
        return Font.custom("DigitalX", size: s);
}

我在一个视图中有一个Text对象如下:

let font : Font = FontGetter.getDigitalXFontOfSize(20.0);

var body: some View {
        HStack {
            Text("some text").font(FontGetter)
        }
}
在iOS中,有选项可以在设置中更改字体大小,它说:“支持动态类型的应用将调整为您所选择的阅读大小”。据我所知,SwiftUI中的文本视图会根据动态类型值自动采用动态缩放字体。
现在我明白无障碍性非常重要,如果用户想要更大的字体,他们应该能够获得等等。我的应用程序是网络游戏的附加组件,需要特定的布局,不遵循非常大或非常小的文本(例如iOS中可用的“accessibilityExtraExtraExtraLarge”)。
一些应用程序(例如iOS的Reddit应用程序)似乎完全忽略了在“设置”应用程序中设置的文本大小。
当您在设置应用程序中更改文本大小滑块时,文本大小也会更改我的应用程序,这是我不想发生的。
我可以在我的应用程序中关闭动态类型支持,并始终呈现我指定的确切大小的字体吗? 如果可以,如何做到?
我可以为我在应用程序中使用的特定文本视图禁用动态类型吗?
我花了很多时间在SO上搜索类似的问题,但似乎找不到iOS 13及以上或SwiftUI的解决方案。以前的iOS版本(或swift)没有以同样方式创建的自定义字体缩放,但现在它们似乎可以。
编辑版:在iOS 14中,有一个选项可以创建固定字体大小,如下所示:
func getDigitalXFontOfSize(size s : CGFloat) -> Font {
        return Font.custom("DigitalX", fixedSize: s);
}

看起来这很有效。但我也需要类似iOS 13的东西。

7个回答

9
我可以关闭动态类型支持吗?我能否禁用应用程序中使用的特定文本视图的动态类型?
禁用“动态类型”功能的最佳方法是避免使用文本样式。然而,在您的情况下,我强烈建议考虑此功能,但不要使用其全部功能(谁知道哪天您可能需要它呢?)
除了@multitudes所接受的答案外,似乎有趣的是展示如何使用“动态类型”功能本身提供此类结果而无需停用它。 iOS 15引入了新的内容大小类别限制,其目的是使用“动态类型”功能设置最小和最大尺寸

⚠️ 但是建议仅在特定情况下使用,如WWDC 2021视频中所述:⚠️

请勿使用此API过度限制文本大小。这些设置具有极其重要的功能,对于使用最高文本大小设置的人来说,您应用程序的所有功能都必须可用,并且所有内容都必须清晰可读。

最后,我建议查看这篇有趣的文章,其中描述了如何限制Dynamic Type大小(包括SwiftUI)。


6

一种小技巧

看起来苹果没有直接提供一种影响动态字体最大尺寸的方法。

为了避免非常小的字体大小,可以使用minimumScaleFactor修饰符,比如:

.minimumScaleFactor(0.5)

为避免使用过大的字体,这并不容易。

在我的应用程序中,我获取名为 sizeCategory 的环境变量,并根据此系统变量的值来调整我的字体。

这对您也适用。在您的视图中,您可以在结构体中添加环境变量。然后,如果您知道 .accessibilityExtraExtraLarge 会破坏您的布局,您可以像这样进行调整:

struct ContentView: View {
    @Environment(\.sizeCategory) var sizeCategory

    var body: some View {
       Text("Hello World")
         .font(sizeCategory == .accessibilityExtraExtraLarge ?
           .custom("Helvetica", size: 23, relativeTo: .headline) :      
           .custom("Helvetica", size: 33, relativeTo: .headline))
         .minimumScaleFactor(0.5)
    }
}

我没有您的完整代码来测试,但我会将以下内容添加到您的函数中,它应该可以正常工作:
func getDigitalXFontOfSize(size s : CGFloat) -> Font {
    if font(sizeCategory == .accessibilityExtraExtraLarge {
        return Font.custom("DigitalX", size: s - 10)
    } else {
        return Font.custom("DigitalX", size: s)
}

希望这能有所帮助。我想在函数内使用switch语句也是一个不错的主意!

5

如何在iOS 15.0+上完全禁用字体缩放

我发现你可以通过在根视图上设置.dynamicTypeSize(.large)来在整个应用程序范围内禁用此功能。(.large似乎是默认值)。

它的行为类似于.preferredColorScheme,会向下传递到所有子视图。

因此,当您在根视图上设置了dynamicTypeSize后,所有指定了固定字体大小的字体将不再缩放。


禁用整个应用程序的动态字体?这是一个糟糕的建议,除非你从不尝试将代码发布到生产环境。 - joshuakcockrell
这取决于你正在构建什么。在我的情况下,我正在开发一个概念验证应用程序,该应用程序还没有准备好进行此适应。或者也许您想使用自己的自定义设置来控制此项功能。但我并不主张您应该这样做,我只是说如果您因某种原因需要这样做,那么可以这样做。 - bjorn.lau

4

iOS 15+

使用 .dynamicTypeSize(DynamicTypeSize)

示例:限制为默认大小

Text("")
    .font(Font.custom("SourceCodePro-Regular", size: 16))
    .dynamicTypeSize(.large) // Forces .large

示例:限制为默认(或更小)

(如果用户在其iOS设置中选择了较小的字体大小,则允许此选项。如果用户选择了较大的字体,这只会强制使用 .large

Text("")
    .font(Font.custom("SourceCodePro-Regular", size: 16))
    .dynamicTypeSize(...DynamicTypeSize.large) // Use a range

示例:范围限制

(如果用户在其iOS设置中使用了更大/更小的字体大小,这将进行限制。)

Text("")
    .font(Font.custom("SourceCodePro-Regular", size: 16))
    .dynamicTypeSize(.small ... .accessibility1) // Use a range

2

如果有人正在寻找一个固定大小的系统字体(就像我一样):

.font(.system(size: 8))

(适用于iOS 14,我不确定是否适用于13)

在UIKit中: let font = UIFont.monospacedSystemFont(ofSize: yourFontSize) - Womble

1
这是对我有用的内容,
Text("Hello")
            .font((sizeCategory == .extraExtraExtraLarge || sizeCategory == .extraExtraLarge) ?
                       .custom("Helvetica", size: 110) :
                       .custom("Helvetica", size: 130))
            .minimumScaleFactor(0.5)
            .foregroundColor(.white)

0

最终,我找到了一种将UIFont转换为Font的解决方案。我已经测试过它,在我的设备上可以正常工作。

您可以在iOS13及以上版本上使用此代码。

extension Font {
    static let fontName = "Quicksand-Light_Bold"
    static func quickSand(size: CGFloat) -> Font {
        if let uifont =  UIFont(name: fontName, size: size) {
            return Font(uifont as CTFont)
        }
        return Font.custom(fontName, size: size)
    }
}

UIFont转换为字体


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接