Project structure, localization, dependencies and assets

Domains: Flutter

How do I include image assets for Flutter? What about multiple resolutions?

While iOS treats images and assets as distinct items, Flutter apps have only assets. Resources that are placed in the Images.xcasset folder on iOS, are placed in an assets folder for Flutter. As with iOS, assets are any type of file, not just images. For example, you might have a JSON file located in the my-assets folder:

my-assets/data.json

Declare the asset in the pubspec.yaml file:

assets:
 - my-assets/data.json

And then access it from code using an AssetBundle:

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('my-assets/data.json');
}

For images, Flutter follows a simple density-based format like iOS. Image assets might be 1.0x, 2.0x, 3.0x, or any other multiplier. The so-called devicePixelRatio expresses the ratio of physical pixels in a single logical pixel.

Assets are located in any arbitrary folder—Flutter has no predefined folder structure. You declare the assets (with location) in the pubspec.yaml file, and Flutter picks them up.

For example, to add an image called my_icon.png to your Flutter project, you might decide to store it in a folder arbitrarily called images. Place the base image (1.0x) in the images folder, and the other variants in sub-folders named after the appropriate ratio multiplier:

images/my_icon.png       // Base: 1.0x image
images/2.0x/my_icon.png  // 2.0x image
images/3.0x/my_icon.png  // 3.0x image

Next, declare these images in the pubspec.yaml file:

assets:
 - images/my_icon.png

You can now access your images using AssetImage:

return AssetImage("images/a_dot_burr.jpeg");

or directly in an Image widget:

@override
Widget build(BuildContext context) {
  return Image.asset("images/my_image.png");
}

For more details, see Adding Assets and Images in Flutter.

Where do I store strings? How do I handle localization?

Unlike iOS, which has the Localizable.strings file, Flutter doesn’t currently have a dedicated system for handling strings. At the moment, the best practice is to declare your copy text in a class as static fields and access them from there. For example:

class Strings {
  static String welcomeMessage = "Welcome To Flutter";
}

You can access your strings as such:

Text(Strings.welcomeMessage)

By default, Flutter only supports US English for its strings. If you need to add support for other languages, include the flutter_localizations package. You might also need to add Dart’s intl package to use i10n machinery, such as date/time formatting.

dependencies:
  # ...
  flutter_localizations:
    sdk: flutter
  intl: "^0.15.6"

To use the flutter_localizations package, specify the localizationsDelegates and supportedLocales on the app widget:

import 'package:flutter_localizations/flutter_localizations.dart';

MaterialApp(
 localizationsDelegates: [
   // Add app-specific localization delegate[s] here
   GlobalMaterialLocalizations.delegate,
   GlobalWidgetsLocalizations.delegate,
 ],
 supportedLocales: [
    const Locale('en', 'US'), // English
    const Locale('he', 'IL'), // Hebrew
    // ... other locales the app supports
  ],
  // ...
)

The delegates contain the actual localized values, while the supportedLocales defines which locales the app supports. The above example uses a MaterialApp, so it has both a GlobalWidgetsLocalizations for the base widgets localized values, and a MaterialWidgetsLocalizations for the Material widgets localizations. If you use WidgetsApp for your app, you don’t need the latter. Note that these two delegates contain “default” values, but you’ll need to provide one or more delegates for your own app’s localizable copy, if you want those to be localized too.

When initialized, the WidgetsApp (or MaterialApp) creates a Localizations widget for you, with the delegates you specify. The current locale for the device is always accessible from the Localizations widget from the current context (in the form of a Locale object), or using the Window.locale.

To access localized resources, use the Localizations.of() method to access a specific localizations class that is provided by a given delegate. Use the intl_translation package to extract translatable copy to arb files for translating, and importing them back into the app for using them with intl.

For further details on internationalization and localization in Flutter, see the internationalization guide, which has sample code with and without the intl package.

Note that before Flutter 1.0 beta 2, assets defined in Flutter were not accessible from the native side, and vice versa, native assets and resources weren’t available to Flutter, as they lived in separate folders.

What is the equivalent of CocoaPods? How do I add dependencies?

In iOS, you add dependencies by adding to your Podfile. Flutter uses Dart’s build system and the Pub package manager to handle dependencies. The tools delegate the building of the native Android and iOS wrapper apps to the respective build systems.

While there is a Podfile in the iOS folder in your Flutter project, only use this if you are adding native dependencies needed for per-platform integration. In general, use pubspec.yaml to declare external dependencies in Flutter. A good place to find great packages for Flutter is on the pub.dev site.

Similar pages

Page structure
Terms

Flutter

Assets

Widget