Flutter世界国家信息插件world_countries的使用
Flutter世界国家信息插件world_countries的使用
概述
world_countries
是一个基于ISO标准且完全测试过的包,提供了关于世界各国、货币、语言等信息。这些信息以编译时、树可摇动的常量密封类形式提供,并支持自定义选择器。这是一个在 sealed_countries
包基础上的Flutter封装,扩展了所有国家、货币、语言的数据,如代码、名称、翻译等,并提供了用于显示国家、语言、货币列表和选择器的现成小部件。国旗是通过优化的 CustomPainter
创建的,底层依赖于 world_flags
包。
目录
特性
该包提供了以下现成的小部件和类:
CountryPicker
- 显示世界各国列表的选择器小部件。PhoneCodePicker
- 显示电话区号列表的选择器小部件。CurrencyPicker
- 显示法定货币列表的选择器小部件。LanguagePicker
- 显示自然语言列表的选择器小部件。
你也可以通过扩展 BasicPicker
来创建自己的选择器。
TypedLocaleDelegate
- 用于自动翻译选择器的区域设置委托。提供包括所有GlobalMaterialLocalizations
和GlobalCupertinoLocalizations
区域设置在内的翻译。PickersThemeData
,FlagThemeData
,CountryTileThemeData
,CurrencyTileThemeData
和LanguageTileThemeData
是主题扩展,可以在ThemeData
中使用,以指定全局选择器主题或瓷砖主题(例如国家标志调整或构建器)。
演示
要预览示例中的演示,可以访问 此网页 使用 Chrome 浏览器(版本 119 或更高)。请允许最多 10 秒的时间进行初始字体和数据缓存。
注意:请记住,演示是使用 Flutter WASM 构建的,处于非常早期的 alpha 阶段,因此性能可能受到影响。
开始使用
要使用此包,你需要 Flutter 版本 3.19+。在你的 pubspec.yaml
文件中添加 world_countries
作为依赖项。
dependencies:
world_countries: any
用法
你可以直接使用提供的小部件,或者使用它们的方法:
searchSuggestions
(用于SearchAnchor
的suggestionsBuilder
)showInModalBottomSheet
showInSearch
showInDialog
本地化
为了自动翻译选择器,只需在你的应用小部件中添加委托:
MaterialApp(localizationsDelegates: [TypedLocaleDelegate()])
然后你也可以通过 context.maybeLocale
获取器从上下文中提取此委托数据(从 BuildContext
中)。
你还可以通过提供翻译参数来强制选择器使用特定的区域设置(例如,translation: IsoLocale.withTranslationsCache(LangEng())
将显示英文名称)。
包还提供了对
TypedLocale
和IsoLocale
类的访问,允许你使用类型安全版本的默认Locale
。你也可以在translation()
和maybeTranslation()
方法中利用它们(可以与国家/货币/语言数据一起使用)。
示例
以下是一个完整的示例代码,展示了如何使用 world_countries
包中的小部件:
import "dart:async" show unawaited;
import "package:flutter/material.dart";
import "package:flutter_localizations/flutter_localizations.dart";
import "package:world_countries/world_countries.dart";
void main() => runApp(
MaterialApp(
home: const MainPage(),
theme: ThemeData(
extensions: const <ThemeExtension>[
PickersThemeData(primary: true), // 指定全局选择器主题。
FlagThemeData(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(4))),
),
],
),
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
TypedLocaleDelegate(
localeMapResolution: [
LocaleEntry(
Locale("pt", "BR"),
IsoLocale(LangPor(), country: CountryPrt()),
),
],
),
],
supportedLocales: [
for (final locale in kMaterialSupportedLanguages) Locale(locale),
const Locale("pt", "PT"),
const Locale("pt", "BR"),
],
),
);
class MainPage extends StatefulWidget {
const MainPage({
super.key,
this.basicPicker = const CountryPicker(disabled: [CountryAbw()]),
});
final CountryPicker basicPicker;
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> with SingleTickerProviderStateMixin {
late CountryPicker picker = widget.basicPicker.copyWith(onSelect: onSelect);
void onSelect(WorldCountry newCountry) {
debugPrint("New country selected: $selectedCountry");
setState(
() => picker = picker.copyWith(
chosen: selectedCountry == newCountry ? const [] : [newCountry],
),
);
}
void onFabPressed({bool isLongPress = false}) {
final phonePicker = PhoneCodePicker.fromCountryPicker(picker);
unawaited(
isLongPress
? phonePicker.showInDialog(context)
: phonePicker.showInModalBottomSheet(context),
);
}
void onAppBarSearchLongPressed() => unawaited(picker.showInSearch(context));
WorldCountry? get selectedCountry => picker.chosen?.firstOrNull;
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
actions: [
SearchAnchor(
isFullScreen: false,
viewConstraints: const BoxConstraints(minWidth: 220, maxWidth: 320),
builder: (_, controller) => GestureDetector(
onLongPress: onAppBarSearchLongPressed,
child: IconButton(
onPressed: controller.openView,
icon: const Icon(Icons.search),
),
),
suggestionsBuilder: picker.searchSuggestions,
),
],
),
body: Center(
child: MaybeWidget(
selectedCountry?.maybeTranslation(BasicLocale(LangEng()))?.name,
Text.new,
orElse: const Text(
"Please select country by pressing on the search icon",
),
),
),
floatingActionButton: GestureDetector(
onLongPress: () => onFabPressed(isLongPress: true),
child: FloatingActionButton(
onPressed: onFabPressed,
child: const Icon(Icons.search),
),
),
);
}
更多用法示例,请参见 /example
文件夹。
数据
选择器提供了大量关于国家、语言和货币的信息:
PhoneCodePicker
和CountryPicker
处理WorldCountry
数据。LanguagePicker
- 处理NaturalLanguage
和脚本数据。CurrencyPicker
- 处理FiatCurrency
数据。
附加信息
有关使用此包的更多信息,请查阅API文档。如果你有任何问题或建议,请在GitHub仓库中提交。欢迎提交PR或提出想法。如果你喜欢这个包,请给它一个星标或点赞。
参考资料和致谢
此包受 MIT 许可证保护。详情请参阅 LICENSE。此包的依赖项受其各自的许可证保护(可以在各自的文件夹下的 LICENSE 和 NOTICE 文件中找到)。
常见问题
我不喜欢选择器中默认的瓷砖UI
答:每个选择器都有一个 itemBuilder
参数,提供对特定列表项属性的访问。例如,这是如何在 CountryPicker
中仅显示表情符号旗帜:
CountryPicker(
itemBuilder: (country, {isDense}) => EmojiFlag.platformDefault(country.item),
);
为什么我应该使用这个包而不是其他任何国家/货币/语言选择器包?
- 每个旗帜都是一个小部件:此包不使用沉重的SVG或其他资产来显示选择器中的国家旗帜。所有旗帜都是声明式优化的
CustomPainter
。这意味着你不必担心预缓存、增加应用大小、平台依赖的旗帜外观等问题。并且由于它是小部件,你可以随时更改其外观——形状、装饰、宽高比等。例如,如何轻松更改基于资产的旗帜的宽高比而不拉伸/缩小它们。 - 完全无障碍:所有选择器都经过精心设计,考虑了无障碍性,确保与屏幕阅读器和辅助技术无缝集成。
- 最新的旗帜:此包确保准确及时的旗帜表示,反映当前设计。与其他包或表情符号/字体集不同,这些包或集通常使用过时的旗帜,此包提供最新型号的旗帜(例如,2013年的阿富汗旗帜在这里正确显示为2021年的设计)。
- 密封类:此包以密封类的形式提供数据,允许你创建自己的实例并像处理现有实例一样处理它们(例如,这在枚举或常规类中是不可能的(不会失去其密封性质),你还可以覆盖现有数据或添加新数据等)。
- 无第三方依赖:此包没有第三方依赖,确保你不会遇到任何依赖冲突问题(甚至没有
meta
,因为这一点)。 - 丰富的数据:此包提供的数据比任何其他包都多,加上大量的翻译(所有
GlobalMaterialLocalizations
和GlobalCupertinoLocalizations
区域设置和更多)。 - 类型安全:此包中的契约和类型非常强大,确保你的代码是强类型且定义明确。
- 高代码覆盖率:此包的代码几乎有100%的测试覆盖率,近5000个测试(150+在此包中,4828+在底层Dart包中)确保可靠性和稳定性。
- 全面的文档:此包为每个非代码生成的公共成员提供完整文档,通常带有示例,确保清晰易用。
- 行业采用:此包被多家欧洲公司积极用于生产,确保其在实际场景中的有效性和稳健性。
- MIT许可:此包及其源代码发布在 MIT 许可下,这是一种宽松的许可,允许用户使用、修改和分发代码,而无需担心法律影响。MIT 许可被认为是大多数其他开源许可更好的选择,因为它提供了灵活性,允许用户将代码纳入他们的项目中,而不必担心法律后果。
更多关于Flutter世界国家信息插件world_countries的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter世界国家信息插件world_countries的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用world_countries
插件来获取和显示世界国家信息的代码案例。这个插件可以帮助你获取国家的名称、代码、区域、货币等信息。
首先,你需要在pubspec.yaml
文件中添加world_countries
依赖:
dependencies:
flutter:
sdk: flutter
world_countries: ^2.0.0 # 请注意版本号,使用最新的稳定版本
然后运行flutter pub get
来获取依赖。
接下来,你可以在你的Flutter项目中使用这个插件。以下是一个简单的示例,展示如何获取并显示所有国家的名称和代码:
import 'package:flutter/material.dart';
import 'package:world_countries/world_countries.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'World Countries Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: WorldCountriesScreen(),
);
}
}
class WorldCountriesScreen extends StatefulWidget {
@override
_WorldCountriesScreenState createState() => _WorldCountriesScreenState();
}
class _WorldCountriesScreenState extends State<WorldCountriesScreen> {
List<Country> countries = [];
@override
void initState() {
super.initState();
loadCountries();
}
Future<void> loadCountries() async {
countries = await WorldCountries.getAllCountries();
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('World Countries'),
),
body: countries.isEmpty
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: countries.length,
itemBuilder: (context, index) {
Country country = countries[index];
return ListTile(
title: Text('${country.name} (${country.code})'),
subtitle: Text('Region: ${country.region}, Currency: ${country.currency}'),
);
},
),
);
}
}
在这个示例中:
WorldCountries.getAllCountries()
方法用于异步获取所有国家的列表。- 在
initState
方法中调用loadCountries
来加载国家数据,并在数据加载完成后调用setState
来更新UI。 - 使用
ListView.builder
来构建一个滚动列表,显示每个国家的名称、代码、区域和货币信息。
你可以根据需要进一步自定义和扩展这个示例,例如添加搜索功能、筛选特定区域的国家、显示更多国家信息等。这个插件提供了丰富的国家数据,你可以查阅其文档以了解更多可用属性和方法。