In this tutorial I'm going to show you how to setup and use custom font families in Flutter.
In Flutter, we can use TextStyle
to define custom style for the text to be displayed. One of the TextStyle
's properties is fontFamily
. By default, Flutter uses Roboto font. With fontFamily
property, you can change it to use any font you want. Below are the steps how to setup and use custom font families in a Flutter application.
1. Copy the Font Resources to Your Project For each font family you want to use
First of all, you need to have the .ttf
files of the fonts. If you don't already have the resources, you can search in the Internet.
After you get the files, copy them to a directory inside your Flutter application project. For example, you can use assets/fonts
directory and place the files there.
assets
fonts
OpenSans-Regular.ttf
Raleway-Regular.ttf
2. Define the Fonts in pubspec.yaml
File
In pubspec.yaml
, there must be flutter
node. Below, it's necessary to have a node child named fonts
, just add it if it's not already present. There, you can define your fonts as list members, each font has family
and fonts
properties. family
is used to define the name, while fonts
contains the path the the resource. Make sure the path is valid, otherwise you will get: Error: unable to locate asset entry in pubspec.yaml
.
flutter:
fonts:
- family: OpenSans
fonts:
- asset: assets/fonts/OpenSans-Regular.ttf
- family: Raleway
fonts:
- asset: assets/fonts/Raleway-Regular.ttf
3. Use the Fonts
You can set a font as the theme's default or only use it in a specific widget.
For using the font as the default, you need to pass the font name defined in pubspec.yaml
as the fontFamily
of theme
. It also affects the app bar unless you override the style.
return MaterialApp(
title: 'Welcome to Flutter',
theme: ThemeData(fontFamily: 'Raleway'),
home: MyAppHome(),
);
To use a font family in a specific widget, use TextStyle
with the font name passed as fontFamily
. You can also set the font style or adding decoration.
const Text(
'ABC',
style: TextStyle(
fontSize: 32.0,
fontFamily: 'OpenSans',
fontStyle: FontStyle.italic,
decoration: TextDecoration.underline,
),
),
Below is the full code which uses Raleway as the default theme font, while OpenSans sets as the font for the second Text
widget.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
theme: ThemeData(fontFamily: 'Raleway'),
home: MyAppHome(),
);
}
}
class MyAppHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Font Family Tutorial by Woolha.com'),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: const Text(
'ABCDE',
style: TextStyle(fontSize: 32.0),
),
),
Container(
child: const Text(
'ABCDE',
style: TextStyle(
fontSize: 32.0,
fontFamily: 'OpenSans',
fontStyle: FontStyle.italic,
decoration: TextDecoration.underline,
),
),
),
],
)
),
);
}
}
Output:
How Does Flutter Match Weight and Style?
In pubspec.yaml
, it's possible to add weight
and style
properties for each asset. Is it really used by Flutter?
Actually Flutter engines matches fonts within a family based on the metadata defined in the .ttf
resource [source]. The style descriptors in pubspec.yaml
are obsolote.
For font weight, Flutter only supports multiplication of 100, with 100 as the lowest value (the lightest) and 900 as the maximum value (the boldest). If the font weight value described in the resource metadata is not multiplication of 100, Flutter will map it to a supported value.
If you only define the regular version of a font family and you set the fontWeight
or fontStyle
, the Flutter engine will create that custom variant though the result may not be exactly the same with the actual resource (if it exists and included). However the reverse may not work. If you have an italic style resource and you set the fontStyle
to FontStyle.normal
, usually it will not work.