Flutter基础——工程结构、本地化、依赖和资源

Posted by lingjye on July 18, 2019

Assets

在iOS中images和assets是两种不同的东西,而Flutter中只有assets。被放到iOS中Images.xcasset文件夹下的资源在Flutter中被放到了assets文件夹中。assets可以是任意类型的文件,而不仅仅是图片。

例如把json文件放到my-assets文件夹中。

1
my-assets/mydata.json

在pubspec.yaml文件中声明assets:

1
2
3
assets:
	// 相对路径
	- my-assets/mydata.json

然后在代码中使用AssetBundle来访问:

1
2
3
4
5
import 'package:flutter/services.dart';

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

对于图片,Flutter 像 iOS 一样,遵循了一个简单的基于像素密度的格式。例如ioS中常见的图片后缀@1x,@2x,@3x等。Flutter中的assets可以被放到任何文件夹家中,在pubspec.ymal指明assets的位置,编译器会自动识别。

例如:

1
2
3
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

然后在pubspec.ymal中声明这些图片:

1
2
assets:
 - images/my_icon.jpeg

可以使用AssetImage来访问这些图片:

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

或者在Image widget中直接使用:

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

如果要批量加载,可以只指定资源的目录,此目录下的资源文件会被批量加载,但是如果该目录下还包含子目录,需要将单独指定子目录:

1
2
3
assets:
 - images/
 - images/homeimgs/

另外对于1x,2x,3x的图片,可以分别指定不同的文件目录,来存放不同分辨率的图片,Flutter会自动根据设备分辨率识别。

例如:

1
2
3
4
images/xxx.jpg 存放1.0x的图片
images/2.0x/xxx.jpg 存放2.0x的图片
images/3.0x/xxx.jpg 存放3.0x的图片

在pubspec.yaml中只需要声明1.0x的图片即可

1
2
assets:
 - images/icon.jpg

本地化

在iOS中有Localizable.strings文件,而Flutter目前并没有一个用于处理字符串的系统。目前最好的办法就是将文本拷贝到静态区中:

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

访问:

1
Text(Strings.welcomeMessage)

默认情况下,Flutter只支持美式英语字符串。如果要支持其他语言,需要引入 flutter_localizations包。可能也要引入intl包来支持其他的i10n机制,比如日期/时间格式化。

1
2
3
4
5
dependencies:
  # ...
  flutter_localizations:
    sdk: flutter
  intl: "^0.15.6"

要使用 flutter_localizations 包,还需要在 app widget 中指定 localizationsDelegates 和 supportedLocales。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
  ],
  // ...
)

这些代理包括了实际的本地化值,并且 supportedLocales 定义了 App 支持哪些地区。

上面的例子使用了一个 MaterialApp ,所以它既有 GlobalWidgetsLocalizations 用于基础 widgets,也有 MaterialWidgetsLocalizations 用于 Material wigets 的本地化。如果使用了 WidgetsApp ,则无需包括后者。注意,这两个代理虽然包括了“默认”值,但如果想让你的 App 本地化,你仍需要提供一或多个代理作为 App 本地化副本。

当初始化时,WidgetsApp 或 MaterialApp 会使用指定的代理创建一个 Localizations widget。Localizations widget 可以随时从当前上下文中访问设备的地点,或者使用 Window.locale。

要访问本地化文件,使用 Localizations.of() 方法来访问提供代理的特定本地化类。如需翻译,使用 intl_translation 包来取出翻译副本到 arb 文件中。把它们引入 App 中,并用 intl 来使用它们。

依赖

在Flutter中使用Dart构建系统和Pub包管理器来处理依赖,类似于iOS中的Cocoapod。这些工具将本机Android和iOS包装应用程序的构建指派给相应的构建系统。使用pubspec.yaml来声明外部依赖。

本文Demo