Android
Android

Reputation: 939

Flutter not picking custom fonts based on fontWeight

How to choose different font weights without specifying new family for each weight?

  fonts:
 - family: Montserrat
   fonts:
     - asset: assets/fonts/Montserrat-Regular.ttf
       weight: 100
     - asset: assets/fonts/Montserrat-Bold.ttf
       weight: 700
 - family: MontserratBold
   fonts:
     - asset: assets/fonts/Montserrat-Bold.ttf

and the widgets:

                      child: Text(
                    'TEST',
                    style: TextStyle(
                      fontSize: 17.4,
                      fontFamily: 'Montserrat',
                      fontWeight: FontWeight.w700,
                      color: Colors.black87,
                    ),
                  ),

..

                      child: Text(
                    'TEST2',
                    style: TextStyle(
                        fontSize: 17.4,
                        fontFamily: 'MontserratBold',
                        color: Colors.black87),
                  ),

The actual Montserrat-Bold is only used with 'TEST2'. I have tried using 'Packages get' in pubspec.yaml and restarting the app.

Upvotes: 44

Views: 32717

Answers (8)

Jannie Theunissen
Jannie Theunissen

Reputation: 30154

From the docs we get this list of constants:

w100 Thin, the least thick
w200 Extra-light
w300 Light
w400 Normal / regular / plain
w500 Medium
w600 Semi-bold
w700 Bold
w800 Extra-bold
w900 Black, the most thick

So in pubspec you can define your custom font like this:

  fonts:
   - family: Montserrat
     fonts:
       - asset: fonts/Montserrat-Regular.ttf
       - asset: fonts/Montserrat-SemiBold.ttf
         weight: 600
       - asset: fonts/Montserrat-Bold.ttf
         weight: 700

and use it in your code like this:

final h1 = new TextStyle(
    fontSize: 24.0, 
    fontWeight: FontWeight.w600  // semi-bold
);

Upvotes: 60

Moaz El-sawaf
Moaz El-sawaf

Reputation: 3039

The reason that makes your specified font weight ignored is stated in the official docs here:

Note that defining the weight property does not override the actual weight of the font. You would not be able to access RobotoMono-Bold with FontWeight.w100, even if its weight was set to 100.

The font weight actually is metadata stored in the font file, Flutter does not override this metadata with your specified one.

One possible workaround for that is to change the metadata that specifies the font weight of the font file, check this answer to do that.

Upvotes: -1

Gregory Conrad
Gregory Conrad

Reputation: 1577

Adding onto @szotp's answer, here is how you can modify the weights for a set of font files in a python script that flutter will respect. Create a src and out directory, and put the original font files in the src directory. The script below will put the font files with the correct metadata in the out directory.

import os
from fontTools import ttLib

# Declare your fonts and their correct weights here, like below
to_change = {
    'Neue Radial B Thin Italic.ttf': 100,
    'Neue Radial B Thin.ttf': 100,
    'Neue Radial B Extra Bold Italic.ttf': 800,
    'Neue Radial B Bold.ttf': 700,
    'Neue Radial B Book.ttf': 500,
    'Neue Radial B Regular Italic.ttf': 400,
    'Neue Radial B Light.ttf': 300,
    'Neue Radial B Book Italic.ttf': 500,
    'Neue Radial B Regular.ttf': 400,
    'Neue Radial B Extra Bold.ttf': 800,
    'Neue Radial B Extra Light.ttf': 200,
    'Neue Radial B Light Italic.ttf': 300,
    'Neue Radial B Extra Light Italic.ttf': 200,
    'Neue Radial B Bold Italic.ttf': 700,
    'Neue Radial B Medium.ttf': 600,
    'Neue Radial B Black.ttf': 900,
    'Neue Radial B Black Italic.ttf': 900,
    'Neue Radial B Medium Italic.ttf': 600,
}

for file, weight in to_change.items():
    with ttLib.TTFont(os.path.join('src', file)) as tt:
        tt['OS/2'].usWeightClass = weight
        tt.save(os.path.join('out',file))

Upvotes: 3

Kirill Nikitin
Kirill Nikitin

Reputation: 29

You can add or reduce the font boldness alongside you already have style: TextStyle(...)

Use .apply(fontWeightDelta: int)

For example

style: TextStyle(
         fontSize: 17.4,
         fontFamily: 'Montserrat',
         fontWeight: FontWeight.w700,
         color: Colors.black87,
       ).apply(fontWeightDelta: 2), 

delta 1 means +100 to FontWeight (delta -1 means -100). So, this makes you FontWeight 900 instead of 700

For the fontWeight, the delta is applied to the FontWeight enum index values, so that for instance style.apply(fontWeightDelta: -2) when applied to a style whose fontWeight is FontWeight.w500 will return a TextStyle with a FontWeight.w300.

https://api.flutter.dev/flutter/painting/TextStyle/apply.html

Upvotes: 1

szotp
szotp

Reputation: 2622

Font & style settings in pubspec are actually ignored: https://github.com/flutter/flutter/issues/36739#issuecomment-521806077

You need to check what weight is described in metadata inside Montserrat-Bold.ttf, perhaps it's not 700.

For displaying the metadata, you can use this site: https://fontdrop.info/, the font weight is displayed under Data/usWeightClass.

Upvotes: 34

Kirill Karmazin
Kirill Karmazin

Reputation: 6736

The answer by @Jannie Theunissen is sufficient, I just wanted to post here a sample widget to demo all weights for your custom font. Just in case you want to compare them all and decide which one to use.

So here is what you want to do to check your custom font:

  1. Download your font, let's take for example iOS font "San Francisco", you can download it here.

  2. Put it in your your_app/assets/fonts folder (you just need .ttf files).

  3. Add it to the pubspec.yaml file (mind the indents and dashes, they matter):

    fonts:
    - family: SanFrancisco
      fonts:
        - asset: assets/fonts/SFUIDisplay-Ultralight.ttf
          weight: 100
        - asset: assets/fonts/SFUIDisplay-Thin.ttf
          weight: 200
        - asset: assets/fonts/SFUIDisplay-Light.ttf
          weight: 300
        - asset: assets/fonts/SFUIDisplay-Regular.ttf
          weight: 400
        - asset: assets/fonts/SFUIDisplay-Medium.ttf
          weight: 500
        - asset: assets/fonts/SFUIDisplay-Semibold.ttf
          weight: 600
        - asset: assets/fonts/SFUIDisplay-Bold.ttf
          weight: 700
        - asset: assets/fonts/SFUIDisplay-Heavy.ttf
          weight: 800
        - asset: assets/fonts/SFUIDisplay-Black.ttf
          weight: 900
    
  4. Add this demo widget as a body to your Scaffold:

    class FontWeightsDemo extends StatelessWidget {
      final String font = "SanFrancisco";
      final double size = 20.0;
      final double height = 45.0;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.white,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                height: height,
                child: Center(
                    child: Text(
                  "This text has weight w100",
                  style: TextStyle(
                      fontFamily: font,
                      fontSize: size,
                      fontWeight: FontWeight.w100),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w200",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w200),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w300",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w300),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w400",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w400),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w500",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w500),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w600",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w600),
                )),
              ),
              Container(
                height: height,
                child: Center(
                    child: Text(
                      "This text has weight w700",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w700),
                )),
              ),
              Container(
                    height: height,
                    child: Center(
                    child: Text(
                      "This text has weight w800",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w800),
                    )),
                  ),
              Container(
                    height: height,
                    child: Center(
                    child: Text(
                      "This text has weight w900",
                      style: TextStyle(
                          fontFamily: font,
                          fontSize: size,
                          fontWeight: FontWeight.w900),
                )),
              ),
            ],
          ),
        );
      }
    }
    

And this is something you should get:

enter image description here

Just thought it may be useful to someone.

Upvotes: 11

parth jansari
parth jansari

Reputation: 178

you need to add proper indentation at - family.

fonts:
  - family: Montserrat
    fonts:
      - asset: assets/fonts/Montserrat-Regular.ttf
        weight: 100
      - asset: assets/fonts/Montserrat-Bold.ttf
        weight: 700

Upvotes: -1

Daniel Wilson
Daniel Wilson

Reputation: 19824

From my experiments, the weight system seems to be doing some clever things behind the scenes. Maybe it depends on the ttf or the device. I would bet though that FontWeight.w900 might fall into the bold font.

In my code if I specify a weight of 100 (regular) and 200 (for bold), the bold font is not used until I ask for FontWeight.w500. I can tell because I also ask for it in italics, and the bold ttf does not italicize for some reason regardless of weight. So while the weights do "thicken" the font programmatically, catching how and why they fall into a specific font seems to require some guess work.

I then tried with 3 fonts: thin, regular and bold and set them to sensible weights in the pubspec.yaml of 100, 400 and 700 which are described in the docs as thin, normal / regular / plain and bold, and now anything above FontWeight.w400 uses bold.

Hopefully this helps, or someone more knowledgeable comes along

Upvotes: 11

Related Questions