Flutter本地化配置管理插件flutter_floc的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter本地化配置管理插件flutter_floc的使用

简介

Flutter Floc 帮助你快速创建表单,减少样板代码,并提供帮助程序以将视图与表单状态连接起来。

动机

创建表单一直是一项重复性任务。在 Dart 中,有一些包可以帮助你减少所需的样板代码,例如:

formz 是一个提供低级 API 来管理输入状态的包。

flutter_form_bloc 是一个提供高级 API 来管理表单的包,包括验证等。然而,flutter_form_bloc 缺乏一些功能,其中之一就是测试。

我们实际需要一个强大且可测试的表单管理器,并且我们喜欢 bloc。为此,我们基于 flutter_form_bloc 创建了自己的版本。

开始使用

对于如何开始使用 Flutter,可以查看 在线文档,该文档提供了教程、示例、移动开发指南和完整的 API 参考。

安装

在你的 Flutter 应用(pubspec.yaml)依赖列表中添加 flutter_floc 包:

dependencies:
  flutter:
    sdk: flutter

  flutter_floc: ^0.0.0-dev.8

使用

创建一个表单 BLoC

  1. 创建一个名为 register_form_bloc.dart 的新文件(或你喜欢的任何名称)。
  2. 定义一个继承自 FormBloc 的类 RegisterFormBloc
// FormBloc<String>,String 可以替换为你喜欢的任何表单响应类型
class RegisterFormBloc extends FormBloc<String> {

}
  1. 定义表单字段:
// username 是必需的
static final username = FormField<String>(
  name: 'username',
  initialValue: '',
  validators: [
    FieldValidator(Validator.required),
  ],
);

// password 是必需的,并且应该包含至少 6 个字符
static final password = FormField<String>(
  name: 'password',
  initialValue: '',
  validators: [
    FieldValidator(Validator.required),
    FieldValidator(Validator.min6Chars),
  ],
);

// confirmPassword 是必需的,并且应与 "password" 字段具有相同的值
static final confirmPassword = FormField<String>(
  name: 'confirmPassword',
  initialValue: '',
  validators: [
    FieldValidator(Validator.required),
    FieldValidator(
      Validator.confirmPassword,
      fieldSubscriptions: [password],
    ),
  ],
);
  1. 在表单构造函数中添加字段:
class RegisterFormBloc extends FormBloc<String> {
  RegisterFormBloc() {
    addFields([password, username, confirmPassword]);
  }
}
  1. 你可以覆盖 onSubmit 方法,当表单提交并有效时会触发此方法:
@override
void onSubmit(fields) async {
  // 你可以在其中进行 HTTP 调用
  print(fields['username']);
  print(fields['password']);
  print(fields['confirmPassword']);
  emitSuccess('success response : ok');
}

现在让我们为这些功能添加一些 UI。

  1. 在你的小部件树中的某个位置添加一个 FormBlocListener(对于那些来自 bloc 包的人来说,它基于 BlocListener)。FormBlocListener 提供了一些在表单生命周期期间触发的处理器(onSubmittingonSuccessonFailure):
class ExampleForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FormBlocListener<ExampleFormBloc, String>(
      onSubmitting: (context, state) {
        print('Loading...');
      },
      onSuccess: (context, state) {
        print('Success !');
        print(state.response);
      },
      onFailure: (context, state) {
        print('Failure !');
        print(state.response);
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          // 字段位于一个 `TextFieldBlocBuilder` 中,该构建器会在字段状态更改时更新
          TextFieldBlocBuilder<ExampleFormBloc>(
            fieldName: 'username',
            decoration: InputDecoration(hintText: 'Username'),
          ),
          TextFieldBlocBuilder<ExampleFormBloc>(
            fieldName: 'password',
            obscureText: true,
            decoration: InputDecoration(hintText: 'Password'),
          ),
          TextFieldBlocBuilder<ExampleFormBloc>(
            fieldName: 'confirmPassword',
            obscureText: true,
            decoration: InputDecoration(hintText: 'Confirm password'),
          ),
          // 按钮强制字段验证
          MaterialButton(
            onPressed: () {
              context.read<ExampleFormBloc>().validate();
            },
            child: Text('Validate'),
          ),
          // 按钮触发表单提交
          MaterialButton(
            onPressed: () {
              context.read<ExampleFormBloc>().submit();
            },
            child: Text('Submit'),
          )
        ],
      ),
    );
  }
}

至此,你已经完成了第一个 FormBLoC。

验证器

你可以创建简单的验证器,例如一个最小长度为 6 个字符的验证器,如下所示:

String min6Chars(String value, Map<String, dynamic> fields) {
  if (value == null || value.isEmpty || value.runes.length < 6) {
    return 'min 6 chars';
  }
  return null;
}

如果无错误,则返回值为 null。否则,它是一个字符串,返回值被视为 error key,将在 UI 中传递。

要将此验证器添加到字段中,只需将其添加到字段验证器列表中:

static final 6minField = FormField<String>(
  name: '6minField',
  initialValue: '',
  validators: [
    FieldValidator(min6Chars),
  ],
);

依赖其他值的验证器(确认密码情况)

验证器可以依赖于其他字段的值:

String confirmPassword(String value, Map<String, dynamic> fields) {
  if (value != fields['password']) {
    return 'different';
  }
  return null;
}

第二个 fields 参数包含依赖字段。要向验证器添加依赖项,只需在 confirmPassword 验证器的 fieldSubscriptions 名称参数中定义它们:

static final confirmPassword = FormField<String>(
  name: 'confirmPassword',
  initialValue: '',
  validators: [
    FieldValidator(Validator.required),
    FieldValidator(
      Validator.confirmPassword,
      // 我们可以在这里添加其他字段
      fieldSubscriptions: [password],
    ),
  ],
);

更多关于Flutter本地化配置管理插件flutter_floc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地化配置管理插件flutter_floc的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter本地化配置管理插件flutter_floc的示例。这个插件允许你轻松地在Flutter应用中实现本地化(i18n)和国际化(l10n)。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加flutter_floc依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_floc: ^4.0.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

2. 配置Flutter应用

在你的Flutter应用的main.dart文件中,你需要配置flutter_floc。以下是一个基本的配置示例:

import 'package:flutter/material.dart';
import 'package:flutter_floc/flutter_floc.dart';

void main() {
  // 初始化FlutterLocalizations
  FlutterLocalizations.globalLocaleOverride = Locale('en'); // 默认为英语

  // 初始化flutter_floc
  runApp(
    FlocProvider(
      // 传递一个包含所有支持的语言环境的Map
      locales: [
        Locale('en', ''), // 英语
        Locale('zh', ''), // 中文
      ],
      delegate: AppLocalizationDelegate(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: HomeScreen(),
    );
  }
}

class AppLocalizationDelegate extends FlocDelegate {
  @override
  Map<String, Map<String, String>> loadLocalizedStrings() {
    return {
      'en': {
        'welcome': 'Welcome',
        'goodbye': 'Goodbye',
      },
      'zh': {
        'welcome': '欢迎',
        'goodbye': '再见',
      },
    };
  }
}

3. 使用本地化字符串

在你的UI组件中,你可以使用FlocProvider.of(context)来获取本地化字符串。例如:

import 'package:flutter/material.dart';
import 'package:flutter_floc/flutter_floc.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final floc = FlocProvider.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(floc.translate('welcome')),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(floc.translate('welcome')),
            ElevatedButton(
              onPressed: () {
                // 模拟切换语言
                floc.setLocale(Locale('zh'));
              },
              child: Text('Switch to Chinese'),
            ),
            Text(floc.translate('goodbye')),
          ],
        ),
      ),
    );
  }
}

4. 切换语言

在上面的示例中,我们通过一个按钮来模拟切换语言。在实际应用中,你可能会将这个功能集成到应用设置或者一个下拉菜单中。

5. 完整代码

将上述代码片段整合在一起,你将得到一个完整的Flutter应用,它支持英语和中文的本地化:

import 'package:flutter/material.dart';
import 'package:flutter_floc/flutter_floc.dart';

void main() {
  FlutterLocalizations.globalLocaleOverride = Locale('en');

  runApp(
    FlocProvider(
      locales: [
        Locale('en', ''),
        Locale('zh', ''),
      ],
      delegate: AppLocalizationDelegate(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      home: HomeScreen(),
    );
  }
}

class AppLocalizationDelegate extends FlocDelegate {
  @override
  Map<String, Map<String, String>> loadLocalizedStrings() {
    return {
      'en': {
        'welcome': 'Welcome',
        'goodbye': 'Goodbye',
      },
      'zh': {
        'welcome': '欢迎',
        'goodbye': '再见',
      },
    };
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final floc = FlocProvider.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(floc.translate('welcome')),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(floc.translate('welcome')),
            ElevatedButton(
              onPressed: () {
                floc.setLocale(Locale('zh'));
              },
              child: Text('Switch to Chinese'),
            ),
            Text(floc.translate('goodbye')),
          ],
        ),
      ),
    );
  }
}

这个示例展示了如何使用flutter_floc插件在Flutter应用中实现本地化。你可以根据需要扩展这个示例,添加更多的语言和本地化字符串。

回到顶部