Flutter国家选择器插件flutter_country_selector的使用

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

Flutter国家选择器插件flutter_country_selector的使用

简介

flutter_country_selectorphone_form_field 包中的国家选择器,现在它已经被独立出来作为一个单独的包。这个插件支持多种语言的本地化,并且在设计上考虑到了语义化的应用。

功能特性

  • 多语言支持:支持多种语言的本地化。
  • 语义化设计:遵循语义化的设计原则。

示例演示

你可以在这里查看在线示例:Flutter Country Selector Demo

Demo GIF

使用方法

全屏选择器

如果你需要在一个全屏的小部件中显示选择器,可以使用 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 回复

更多关于Flutter国家选择器插件flutter_country_selector的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flutter_country_selector插件的一个详细代码示例。flutter_country_selector是一个流行的Flutter插件,用于选择和显示国家代码及其国旗。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加flutter_country_selector依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_country_selector: ^2.0.0  # 请确保使用最新版本

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

2. 导入插件

在你的Dart文件中导入flutter_country_selector

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

3. 使用插件

下面是一个完整的示例,展示如何在Flutter应用中使用flutter_country_selector

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Country Selector Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Country _selectedCountry = Country('', '', '', '', '');
  String _dialCode = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Country Selector Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CountryPickerDropdown(
              initialSelection: 'US',
              favorite: ['+1', 'CN', 'IN'],
              onChanged: (Country country) {
                setState(() {
                  _selectedCountry = country;
                  _dialCode = country.phoneCode!;
                });
              },
              itemBuilder: (BuildContext context, Country country) {
                return Row(
                  children: <Widget>[
                    FlagWidget(countryCode: country.code!),
                    SizedBox(width: 8),
                    Text(country.name!),
                  ],
                );
              },
            ),
            SizedBox(height: 20),
            Text(
              'Selected Country: ${_selectedCountry.name ?? 'N/A'}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 10),
            Text(
              'Dial Code: $_dialCode',
              style: TextStyle(fontSize: 18),
            ),
          ],
        ),
      ),
    );
  }
}

4. 运行应用

确保你的开发环境已经正确配置,然后运行你的Flutter应用。你应该会看到一个包含国家选择器下拉列表的界面,当你选择一个国家时,会显示所选国家的名称和拨号代码。

解释

  • CountryPickerDropdown:这是一个用于选择国家的下拉列表组件。
  • initialSelection:设置初始选中的国家代码(例如:‘US’)。
  • favorite:设置收藏的国家代码列表,这些国家会在下拉列表顶部显示。
  • onChanged:当用户选择一个国家时,这个回调函数会被调用,并返回选中的Country对象。
  • itemBuilder:用于自定义每个下拉列表项的外观。在这个例子中,每个列表项都包含一个国旗和国家的名称。
  • FlagWidget:这是flutter_country_selector提供的一个用于显示国旗的组件。

通过这种方式,你可以轻松地在Flutter应用中使用flutter_country_selector插件来选择和显示国家及其相关信息。

回到顶部