<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Flutter on and2long 随记</title>
    <link>https://and2long.github.io/tags/flutter/</link>
    <description>Recent content in Flutter on and2long 随记</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Mon, 27 Feb 2023 22:21:33 +0800</lastBuildDate>
    <atom:link href="https://and2long.github.io/tags/flutter/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>【Flutter】国际化代码实现</title>
      <link>https://and2long.github.io/post/flutter%E5%9B%BD%E9%99%85%E5%8C%96%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0/</link>
      <pubDate>Mon, 27 Feb 2023 22:21:33 +0800</pubDate>
      <guid>https://and2long.github.io/post/flutter%E5%9B%BD%E9%99%85%E5%8C%96%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0/</guid>
      <description>&lt;p&gt;Flutter里的国际化，简言之，分为两大步：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;创建本地化资源。&lt;/li&gt;&#xA;&lt;li&gt;创建本地化资源代理，并配置到APP入口函数。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;应用内切换语言，关键点有两个：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;指定应用的语言：设置 MaterialApp 的 locate 参数。&lt;/li&gt;&#xA;&lt;li&gt;取得当前语言对应的本地化资源文件：&lt;code&gt;Localizations.of&amp;lt;S&amp;gt;(context, S)&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Localizations 继承自 StatefulWidget ，内部属性 locale 有变化，child 就会重建。&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;以下，为国际化代码的具体实现：&lt;/p&gt;&#xA;&lt;h1 id=&#34;前提&#34;&gt;前提&lt;/h1&gt;&#xA;&lt;p&gt;在 &lt;code&gt;pubspec.yaml&lt;/code&gt; 文件中添加它和 intl作为依赖&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;flutter pub add flutter_localizations --sdk=flutter&#xA;flutter pub add intl:any&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最终的 &lt;code&gt;pubspec.yaml&lt;/code&gt; 文件中形如：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;dependencies:&#xA;  flutter:&#xA;    sdk: flutter&#xA;  flutter_localizations:&#xA;    sdk: flutter&#xA;  intl: any&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;1-创建本地化资源&#34;&gt;1. 创建本地化资源&lt;/h1&gt;&#xA;&lt;h2 id=&#34;11-创建本地化资源接口声明需要翻译的字段&#34;&gt;1.1 创建本地化资源接口，声明需要翻译的字段。&lt;/h2&gt;&#xA;&lt;p&gt;使用接口定义待翻译字段的好处是：实现类/子类 必须对抽象字段进行赋值，否则编译器会报错。&#xA;相比之下，字典的方式，某个 key 没有赋值，编译器检查不出来，而且，哪些 key 是有用的，哪些 key 没用了，也不好确定。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/// 本地化资源 基类&#xA;abstract class S {&#xA;  /// 本地化资源代理对象&#xA;  static const LocalizationsDelegate delegate = ProjectLocalizationsDelegate();&#xA;&#xA;  /// 根据上下文中的 [Locale] 取得对应的本地化资源。&#xA;  static S of(BuildContext context) {&#xA;    return Localizations.of&amp;lt;S&amp;gt;(context, S)!;&#xA;  }&#xA;&#xA;  /// 支持的语言。&#xA;  /// 如果本地没有保存的语言配置参数，APP会默认使用第一个作为默认语言。&#xA;  static List&amp;lt;Locale&amp;gt; supportedLocales = [&#xA;    const Locale(&amp;#39;en&amp;#39;),&#xA;    const Locale(&amp;#39;ja&amp;#39;),&#xA;    const Locale(&amp;#39;zh&amp;#39;)&#xA;  ];&#xA;&#xA;  // 不需要翻译的字段，直接赋值。&#xA;  static String appName = &amp;#39;AppName&amp;#39;;&#xA;  static String english = &amp;#39;English&amp;#39;;&#xA;  static String japanese = &amp;#39;日本語&amp;#39;;&#xA;  static String simpleChinese = &amp;#39;简体中文&amp;#39;;&#xA;  static Map&amp;lt;String, String&amp;gt; localeSets = {&#xA;    &amp;#39;en&amp;#39;: english,&#xA;    &amp;#39;ja&amp;#39;: japanese,&#xA;    &amp;#39;zh&amp;#39;: simpleChinese&#xA;  };&#xA;&#xA;  // 需要翻译的字段追加到下面，在子类中进行赋值。&#xA;  String get cancel;&#xA;  String get ok;&#xA;  String get readAndAgree;&#xA;  String get privacyPolicy;&#xA;  String get termsOfService;&#xA;&#xA;  String get me;&#xA;  String get settingsLanguage;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;12-创建指定语言的资源类实现上一步中的接口对接口中的成员变量进行赋值&#34;&gt;1.2 创建指定语言的资源类（实现上一步中的接口），对接口中的成员变量进行赋值。&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/// 英文&#xA;class ProjectLocalizationsEN implements S {&#xA;  @override&#xA;  String get cancel =&amp;gt; &amp;#34;Cancel&amp;#34;;&#xA;&#xA;  @override&#xA;  String get ok =&amp;gt; &amp;#34;OK&amp;#34;;&#xA;}&#xA;&#xA;/// 中文&#xA;class ProjectLocalizationsZH implements S {&#xA;  @override&#xA;  String get cancel =&amp;gt; &amp;#34;取消&amp;#34;;&#xA;&#xA;  @override&#xA;  String get ok =&amp;gt; &amp;#34;确定&amp;#34;;&#xA;}&#xA;&#xA;/// 日文&#xA;class ProjectLocalizationsJA implements S {&#xA;  @override&#xA;  String get cancel =&amp;gt; &amp;#34;キャンセル&amp;#34;;&#xA;&#xA;  @override&#xA;  String get ok =&amp;gt; &amp;#34;確定&amp;#34;;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;2-创建本地化资源代理&#34;&gt;2. 创建本地化资源代理&lt;/h1&gt;&#xA;&lt;h2 id=&#34;21-创建本地化资源代理类继承-localizationsdelegate重写-load-方法根据-locale-返回对应语言的资源&#34;&gt;2.1 创建本地化资源代理类（继承 LocalizationsDelegate），重写 load 方法，根据 locale 返回对应语言的资源。&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/// 项目本地化资源代理&#xA;class ProjectLocalizationsDelegate extends LocalizationsDelegate&amp;lt;S&amp;gt; {&#xA;  const ProjectLocalizationsDelegate();&#xA;&#xA;  @override&#xA;  bool isSupported(Locale locale) =&amp;gt; true;&#xA;&#xA;  @override&#xA;  Future&amp;lt;S&amp;gt; load(Locale locale) {&#xA;    return SynchronousFuture&amp;lt;S&amp;gt;(getMaterialTranslation(locale));&#xA;  }&#xA;&#xA;  @override&#xA;  bool shouldReload(ProjectLocalizationsDelegate old) =&amp;gt; false;&#xA;&#xA;  /// 根据 locale 得到对应的本地化资源&#xA;  S getMaterialTranslation(Locale locale) {&#xA;    switch (locale.languageCode) {&#xA;      case &amp;#39;en&amp;#39;:&#xA;        return ProjectLocalizationsEN();&#xA;      case &amp;#39;zh&amp;#39;:&#xA;        return ProjectLocalizationsZH();&#xA;      case &amp;#39;ja&amp;#39;:&#xA;        return ProjectLocalizationsJA();&#xA;      default:&#xA;        return ProjectLocalizationsEN();&#xA;    }&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;22-在程序入口-materialapp-中的-localizationsdelegates-参数中加入自己创建的本地化资源代理类&#34;&gt;2.2 在程序入口 MaterialApp 中的 localizationsDelegates 参数中，加入自己创建的本地化资源代理类。&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;import &amp;#39;package:flutter_localizations/flutter_localizations.dart&amp;#39;;&#xA;&#xA;class MyApp extends StatelessWidget {&#xA;  const MyApp({Key? key}) : super(key: key);&#xA;&#xA;  @override&#xA;  Widget build(BuildContext context) {&#xA;    return Consumer&amp;lt;LocaleStore&amp;gt;(builder: (context, localeStore, _) {&#xA;      return OKToast(&#xA;        movingOnWindowChange: false,&#xA;        child: MaterialApp(&#xA;          onGenerateTitle: (context) =&amp;gt; S.appName,  // 不需要翻译的字段，可以直接类名调用。&#xA;          theme: AppTheme.lightTheme(context),&#xA;          localizationsDelegates: const [&#xA;            GlobalMaterialLocalizations.delegate,&#xA;            GlobalWidgetsLocalizations.delegate,&#xA;            // 项目本地化资源代理&#xA;            S.delegate,&#xA;          ],&#xA;          // 支持的语言&#xA;          supportedLocales: S.supportedLocales,&#xA;          // 指定语言，如果 localStore 里没有保存的语言参数，则直接使用 S 文件中配置的第一个语言。&#xA;          locale: localeStore.languageCode == null&#xA;              ? S.supportedLocales.first&#xA;              : Locale(localeStore.languageCode!),&#xA;          routes: RouteMap.routes,&#xA;          home: const HomePage(),&#xA;          builder: (context, child) =&amp;gt; GestureDetector(&#xA;            onTap: () =&amp;gt; CommonUtils.hideKeyboard(context),&#xA;            child: child,&#xA;          ),&#xA;        ),&#xA;      );&#xA;    });&#xA;  }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;配置完成开始使用&#34;&gt;配置完成，开始使用：&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;不需要翻译的字段，使用方式：&#xA;&lt;code&gt;S.appName&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;支持多语言的字段，使用方式：&#xA;&lt;code&gt;S.of(context).ok&lt;/code&gt;&#xA;&lt;code&gt;S.of(context). cancel&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Flutter 常用命令</title>
      <link>https://and2long.github.io/post/flutter-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</link>
      <pubDate>Sat, 12 Feb 2022 15:00:00 +0000</pubDate>
      <guid>https://and2long.github.io/post/flutter-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/</guid>
      <description>&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;功能描述&lt;/th&gt;&#xA;          &lt;th&gt;命令&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;安装依赖包&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter pub get&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;检查哪些依赖包过期&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter pub outdated&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;检查项目依赖包是否支持空安全&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;dart pub outdated --mode=null-safety&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;升级依赖包&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter pub upgrade&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;升级依赖包-大版本&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter pub upgrade --major-versions&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;将项目代码迁移到空安全&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;dart migrate&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;自动修复代码问题&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;dart fix --apply&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;打包 Android bundle&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter build appbundle&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;打包 Android apks&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter build apk --split-per-abi&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;打包 iOS&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter build ios&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Debug 模式运行&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter run&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Profile 模式运行&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter run --profile&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Release 模式运行&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter run --release&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;指定 Web 渲染模式&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter run -d chrome --web-renderer html&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;发布包检查&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter packages pub publish --dry-run&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;发布包&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;flutter packages pub publish --server=https://pub.dartlang.org&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;</description>
    </item>
  </channel>
</rss>
