This chapter covers recipes of miscellaneous topics in Flutter.
13.1 Using Assets
Problem
You want to bundle static assets in the app.
Solution
Use assets.
Discussion
Data files including JSON, XML, and plain text files
Binary files including images and videos
Assets in pubspec.yaml file
In the runtime, subclasses of AssetBundle class are used to load content from the assets. The load() method retrieves the binary content, while loadString() method retrieves the string content. You need to provide the assets key when using these two methods. The key is the same as asset path declared in pubspec.yaml file. The static application-level rootBundle property refers to the AssetBundle object that contains assets packaged with the app. You can use this property directly to load assets. It’s recommended to use static DefaultAssetBundle.of() method to get the AssetBundle object from build context.
Load string assets
Use AssetImage
For an image asset, it’s common to have multiple variants with different resolutions for the same file. When using AssetImage class to load an asset image, the variant that most closely matches the current device pixel ratio will be used.
Image assets variants
13.2 Using Gestures
Problem
You want to allow user using gestures to perform actions.
Solution
Use GestureDetector widget to detect gestures.
Discussion
onHorizontalDragStart callback means the pointer may begin to move horizontally.
onHorizontalDragUpdate callback means the pointer is moving in the horizontal direction.
onHorizontalDragEnd callback means the pointer is longer in contact with the screen.
Use GestureDetector
13.3 Supporting Multiple Locales
Problem
You want the app to support multiple locales.
Solution
Use Localizations widget and LocalizationsDelegate class .
Discussion
Flutter has built-in support for internalization. If you want to support multiple locales, you need to use Localizations widget. Localizations class uses a list of LocalizationsDelegate objects to load localized resources. LocalizationsDelegate<T> class is a factory of a set of localized resources of type T. The set of localized resources is usually a class with properties and methods to provide localized values.
To create a Localizations object, you need to provide the Locale object and a list of LocalizationsDelegate objects . Most of the time, you don’t need to explicitly create a Localizations object. WidgetsApp widget already creates a Localizations object. WidgetsApp constructor has parameters that are used by the Localizations object. When you need to use localized values, you can use static Localizations.of<T>(BuildContext context, Type type) method to get the nearest enclosing localized resources object of the given type.
flutter_localizations
Enable Flutter localized values
Use localized values
AppLocalizations and localized subclasses
isSupported() method checks whether a locale is supported.
load() method loads the localized resources object for a given locale.
shouldReload() method checks whether the load() method should be called to load the resource again.
Custom LocalizationsDelegate
13.4 Generating Translation Files
Problem
You want to extract localizable strings from code and integrate translated strings.
Solution
Use tools in intl_translation package .
Discussion
Recipe 13-3 describes how to support multiple locales using Localizations widget and LocalizationsDelegate class. The major drawback of solution in Recipe 13-3 is that you need to manually create localized resources classes for all supported locales. Because localized strings are directly embedded in source code, it’s hard to get translators involved. A better choice is to use tools provided by intl_translation package to automate the process. You need to add intl_translation: ^0.17.3 to the dev_dependencies of the pubspec.yaml file.
AppLocalizations using Intl.message()
Load messages
This static AppLocalizations.load() method can be used by the load() method of LocalizationsDelegate class to load AppLocalizations object.
13.5 Painting Custom Elements
Problem
You want to paint custom elements.
Solution
Use CustomPaint widget with CustomPainter and Canvas classes.
Discussion
Parameters of CustomPaint
Name | Type | Description |
---|---|---|
painter | CustomPainter | The painter that paints before the child. |
foregroundPainter | CustomPainter | The painter that paints after the child. |
size | Size | The size to paint. |
child | Widget | The child widget. |
Methods of Canvas
Name | Description |
---|---|
drawArc() | Draw an arc. |
drawCircle() | Draw a circle with specified center and radius. |
drawImage() | Draw an Image object. |
drawLine() | Draw a line between two points. |
drawOval() | Draw an oval. |
drawParagraph() | Draw text. |
drawRect() | Draw a rectangle with specified Rect object. |
drawRRect() | Draw a rounded rectangle. |
Use CustomPaint
13.6 Customizing Themes
Problem
You want to customize themes in Flutter apps.
Solution
Use ThemeData class for Material Design and CupertinoThemeData class for iOS.
Discussion
It’s a common requirement to customize look and feel of an app. For Flutter apps, if Material Design is used, you can use ThemeData class to customize the theme. ThemeData class has a large number of parameters to configure different aspects of the theme. MaterialApp class has the theme parameter to provide the ThemeData object . For iOS style, CupertinoThemeData class has the same purpose to specify the theme. CupertinoApp class also has the theme parameter of type CupertinoThemeData to customize the theme.
If you need to access the current theme object, you can use static Theme.of() method to get nearest enclosing ThemeData object for a build context in Material Design. The similar CupertinoTheme.of() method can be used for iOS style.
Use Theme
13.7 Summary
This chapter discusses miscellaneous topics in Flutter that are useful in different scenarios. In the next chapter, we’ll discuss testing and debugging in Flutter.