Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixing the size of a custom font in SwiftUI iOS 13+ when ignoring Dynamic Type

In an app I'm developing (SwiftUI for iOS13 and above), I have imported a custom font, and I load the font using the following method":

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

I have a Text object in a view as follows:

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

var body: some View {
        HStack {
            Text("some text").font(FontGetter)
        }
}

In iOS, there are options to change the font size in Settings, and it states: "Apps that support Dynamic Type will adjust to your preferred reading size below". And as far as I am aware, the Text view in SwiftUI automatically adopts dynamic scaling of fonts based on the Dynamic Type value.

Now I understand that accessibility is of great importance and if a user wants a bigger font they should be able to get one etc. My app is an add-on for a network game and requires a very specific layout that doesn't adhere to very large nor very small text (like those available in iOS such as accessibilityExtraExtraExtraLarge)

Some apps, like the Reddit app for iOS, seem to ignore the text size set in the Settings App completely.

When you change the text size slider in the Settings app, the text size also changes in my app, which I do not want to happen.

Can I turn off Dynamic Type support in my app and always render the fonts the exact size I specified them? If so, how can it be done?

Can I disable Dynamic Type for specific Text views that I use in the app?

I have spent a many hours searching SO for similar issues, but I can't seem to find a solution for iOS 13 and above or SwiftUI. Previous version of iOS (or swift) didn't scale custom fonts created in the same way, but now they seem to.

EDIT

In iOS 14, there is an option to create a fixed font size as follows:

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

which seems to work. But I also require something like this for iOS 13 also.

like image 223
Tyler Durden Avatar asked Sep 18 '20 13:09

Tyler Durden


People also ask

How do I set dynamic font size in SwiftUI?

SwiftUI comes with support for all of Dynamic Type's font sizes, all set using the . font() modifier. However, if you ask for a specific font and size, you'll find your text no longer scales up or down automatically according to the user's Dynamic Type settings – it remains fixed.

How do I change my custom font in SwiftUI?

To use a custom font, add the font file that contains your licensed font to your app, and then apply the font to a text view or set it as a default font within a container view. SwiftUI's adaptive text display scales the font automtically using Dynamic Type.

What is SwiftUI default font size?

Default font size vs fixed font size of 36 points. System font has many variations for us to choose from. As you might notice, there are weight and design parameters in the Font.

What is dynamic font in iOS?

The Dynamic Type feature allows users to choose the size of textual content displayed on the screen. It helps users who need larger text for better readability. It also accomodates those who can read smaller text, allowing more information to appear on the screen.


3 Answers

A small hack

It seems Apple does not give us a direct way to influence the max size of the dynamic fonts.

To avoid very small font sizes there is the minimumScaleFactor modifier like

.minimumScaleFactor(0.5)

To avoid very large fonts it is not so easy.

What I did in my app is to get the Environment variable called sizeCategory and depending on the value of this system variable, adjusting my font.

It should work for you as well. In your view, you would add the environment variable in your struct. Then if you know that the .accessibilityExtraExtraLarge breaks your layout you can adjust it like this:

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)
    }
}

I do not have your full code to test, but I would add this to your function it should work:

func getDigitalXFontOfSize(size s : CGFloat) -> Font {
    if font(sizeCategory == .accessibilityExtraExtraLarge {
        return Font.custom("DigitalX", size: s - 10)
    } else {
        return Font.custom("DigitalX", size: s)
}

I hope this would help. I guess using a switch statement inside the function could be an idea as well!

like image 188
multitudes Avatar answered Oct 18 '22 18:10

multitudes


Can I turn off Dynamic Type support […] Can I disable Dynamic Type for specific Text views that I use in the app?

The best way to disable the Dynamic Type feature is to avoid using the text styles.
However, in your case, I strongly recommend to take this feature into account without using its full power (you’ll may need it one day, who knows?). 🤔

In addition to the @multitudes accepted answer 👏, it seems interesting to show how the Dynamic Type feature can itself provide this kind of result without being deactivated.

iOS 15 introduced new content size category limits whose goal is to set minimum and maximum sizes with the Dynamic Type feature:🤓

  • minimumContentSizeCategory
  • maximumContentSizeCategory

⚠️ But it’s recommended to use it in specific situations as stated in a WWDC 2021 video: ⚠️

Please do not use this API to unduIy limit text size. These settings serve an extremely important function, and it’s paramount that your app’s functionality is all available, and everything is legible, to people using the highest text size setting.

Finally, I suggest to take a look at this interesting article that describes how to restrict the Dynamic Type sizes if need be.👍

like image 30
XLE_22 Avatar answered Oct 18 '22 18:10

XLE_22


In case anyone was looking for a system font with fixed size (like me):

.font(.system(size: 8))

(works in iOS 14, I don't know about 13)

like image 2
Burgler-dev Avatar answered Oct 18 '22 18:10

Burgler-dev