Flutter国家选择器插件flutter_country_selector的使用
Flutter国家选择器插件flutter_country_selector的使用
简介
flutter_country_selector
是 phone_form_field
包中的国家选择器,现在它已经被独立出来作为一个单独的包。这个插件支持多种语言的本地化,并且在设计上考虑到了语义化的应用。
功能特性
- 多语言支持:支持多种语言的本地化。
- 语义化设计:遵循语义化的设计原则。
示例演示
你可以在这里查看在线示例:Flutter Country Selector Demo
使用方法
全屏选择器
如果你需要在一个全屏的小部件中显示选择器,可以使用 CountrySelector.page
:
Navigator.of(context).push(
MaterialPageRoute(
builder: (ctx) => CountrySelector.page(
onCountrySelected: (country) => Navigator.of(context).pop(country),
),
),
);
模态选择器
如果你需要在一个模态框中显示选择器,可以使用 CountrySelector.sheet
:
showModalBottomSheet(
context: context,
builder: (_) => CountrySelector.sheet(
onCountrySelected: (country) => Navigator.of(context).pop(country),
),
);
本地化
动态本地化
当你需要动态本地化一个国家的名字时,可以使用以下代码:
CountrySelectorLocalization.of(context)?.countryName(isoCode)
支持的语言
以下是支持的语言列表:
- ar
- de
- el
- en
- es
- fa
- fr
- he
- hi
- hu
- it
- ko
- ku
- nb
- nl
- pt
- ru
- sv
- tr
- uk
- ur
- uz
- vi
- zh
设置本地化
以下是一个配置本地化的示例:
const MaterialApp(
locale: Locale('en'),
supportedLocales: [
Locale('en'),
],
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
CountrySelectorLocalization.delegate,
],
// ...
)
自定义旗帜
有些用户可能出于政治或风格原因希望更改某些旗帜,或者添加自己的旗帜。有关如何实现这一点,请参考此问题:GitHub Issue #222
完整示例代码
以下是一个完整的示例代码,展示了如何使用 flutter_country_selector
插件:
import 'package:flutter/material.dart';
import 'package:flutter_country_selector/flutter_country_selector.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
void main() {
runApp(const MyApp());
}
class ThemeConfig extends ValueNotifier<ThemeMode> {
ThemeConfig(super.value);
}
final theme = ThemeConfig(ThemeMode.light);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => AnimatedBuilder(
animation: theme,
builder: (context, _) {
return MaterialApp(
locale: const Locale('en'),
supportedLocales: const [
Locale('en'),
],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
CountrySelectorLocalization.delegate,
],
home: const DemoPage(),
themeMode: theme.value,
darkTheme: ThemeData(
brightness: Brightness.dark,
),
);
},
);
}
class DemoPage extends StatefulWidget {
const DemoPage({super.key});
@override
State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
NavigationType navigationType = NavigationType.page;
bool showDialCode = true;
bool containsFavorite = false;
@override
initState() {
super.initState();
CountrySelector.preloadFlags();
}
void show(BuildContext context) {
switch (navigationType) {
case NavigationType.page:
return Navigator.of(context).push(
MaterialPageRoute(
builder: (ctx) => buildSelectorPage(),
),
);
case NavigationType.dialog:
return showDialog(
context: context,
builder: (_) => Dialog(
child: buildSelectorSheet(),
),
);
case NavigationType.draggableBottomSheet:
return showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
builder: (_) => DraggableScrollableSheet(
initialChildSize: 0.7,
minChildSize: 0.25,
maxChildSize: 0.85,
expand: false,
builder: (context, scrollController) {
return buildSelectorSheet();
},
),
isScrollControlled: true,
);
case NavigationType.modalBottomSheet:
return showModalBottomSheet(
context: context,
builder: (_) => SizedBox(
height: MediaQuery.of(context).size.height - 90,
child: buildSelectorSheet(),
),
isScrollControlled: true,
);
case NavigationType.bottomSheet:
return showBottomSheet(
context: context,
builder: (_) => MediaQuery(
data: MediaQueryData.fromView(View.of(context)),
child: SafeArea(
child: buildSelectorSheet(),
),
),
);
}
}
Widget buildSelectorPage() {
return CountrySelector.page(
onCountrySelected: (country) => Navigator.of(context).pop(country),
favoriteCountries: containsFavorite ? [IsoCode.US] : [],
showDialCode: showDialCode,
);
}
Widget buildSelectorSheet() {
return CountrySelector.sheet(
onCountrySelected: (country) => Navigator.of(context).pop(country),
addFavoritesSeparator: true,
favoriteCountries: containsFavorite ? [IsoCode.US] : [],
showDialCode: showDialCode,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.only(top: 12),
child: Container(
constraints: const BoxConstraints(maxWidth: 600),
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
SwitchListTile(
value: theme.value == ThemeMode.dark,
onChanged: (v) =>
setState(() => theme.value = v ? ThemeMode.dark : ThemeMode.light),
title: const Text('Dark mode'),
),
SwitchListTile(
value: showDialCode,
onChanged: (v) => setState(() => showDialCode = v),
title: const Text('Show dial code'),
),
SwitchListTile(
value: containsFavorite,
onChanged: (v) => setState(() => containsFavorite = v),
title: const Text('Contains favorites'),
),
ListTile(
title: Wrap(
alignment: WrapAlignment.spaceBetween,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
const Text('Country selector: '),
NavigationTypeDropdown(
onChange: (type) => setState(() => navigationType = type),
value: navigationType,
),
],
),
),
ElevatedButton(
onPressed: () => show(context),
child: const Text('Show')),
],
),
),
),
),
),
),
);
}
}
enum NavigationType {
page,
dialog,
draggableBottomSheet,
modalBottomSheet,
bottomSheet,
}
class NavigationTypeDropdown extends StatelessWidget {
final Function(NavigationType) onChange;
final NavigationType value;
const NavigationTypeDropdown({
super.key,
required this.value,
required this.onChange,
});
@override
Widget build(BuildContext context) {
return DropdownButton<NavigationType>(
value: value,
onChanged: (NavigationType? value) {
if (value != null) {
onChange(value);
}
},
items: const [
DropdownMenuItem(
value: NavigationType.page,
child: Text('Page'),
),
DropdownMenuItem(
value: NavigationType.dialog,
child: Text('Dialog'),
),
DropdownMenuItem(
value: NavigationType.draggableBottomSheet,
child: Text('Draggable modal sheet'),
),
DropdownMenuItem(
value: NavigationType.modalBottomSheet,
child: Text('Modal sheet'),
),
DropdownMenuItem(
value: NavigationType.bottomSheet,
child: Text('Bottom sheet'),
),
],
);
}
}
通过以上内容,你可以轻松地将 flutter_country_selector
集成到你的 Flutter 应用中,并根据需要进行自定义和扩展。
更多关于Flutter国家选择器插件flutter_country_selector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复