flutter_country_phone 0.1.1
flutter_country_phone: ^0.1.1 copied to clipboard
Country catalog, localized country picker, SVG flags, and international phone form fields for Flutter apps.
flutter_country_phone #
Country catalog, localized country picker, SVG flags, and international phone form fields for Flutter apps.
flutter_country_phone gives you a reusable foundation for forms that need a
country selector, a phone input with country prefix handling, or a simple way to
render country names and flags. It ships with its own static country catalog and
flag assets, so your app does not need to duplicate those resources.
Features #
- Static country catalog with ISO 3166-1 alpha-2 codes, phone prefixes, and localized country names.
- Package-owned SVG flags through
CountryFlag. CountryBlocto load and reuse the country catalog across fields.CountryFormFieldfor selecting a country inside aForm.PhoneFormFieldfor collecting an international phone number.CountryFieldandPhoneFieldlower-level widgets when you do not need aFormFieldwrapper.- Search by localized country name, ISO code, or phone prefix.
onlyCountriesfiltering for restricted country lists.CountryPhoneFieldStyleplus item/button builders for UI customization.- Locale fallback support for values such as
es,es_MX,es-MX,pt_BR, andpt-BR.
Installation #
Add the package to your pubspec.yaml:
dependencies:
flutter_country_phone: ^0.1.1
The package declares its own flag assets. No extra asset registration is needed in your app.
Basic setup #
Provide a CountryBloc once near the part of the app that uses country or
phone fields:
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_country_phone/flutter_country_phone.dart';
BlocProvider(
create: (_) => CountryBloc()..fetchCountries(),
child: const MyApp(),
)
You can also register CountryBloc in your app-level MultiBlocProvider if
the country catalog is used in multiple features.
Country picker #
Use CountryFormField when the selected country is part of a Form:
CountryFormField(
value: 'US',
decoration: const InputDecoration(
labelText: 'Country',
hintText: 'Select your country',
),
validator: (country) {
if (country == null) return 'Select a country';
return null;
},
onChanged: (country) {
debugPrint(country?.iso2); // US
},
)
Restrict the list when a flow supports only a few countries:
CountryFormField(
onlyCountries: const ['US', 'BR', 'ES'],
showPhoneCode: true,
onChanged: (country) {
debugPrint('${country?.iso2} ${country?.phoneCode}');
},
)
If you need a plain widget instead of a form field, use CountryField:
CountryField(
decoration: const InputDecoration(labelText: 'Country'),
locale: 'pt-BR',
onChanged: (country) {
debugPrint(country.iso2);
},
)
International phone field #
PhoneFormField lets the user select a country first and then enter the
national phone number. The onChanged value is the international number string
generated by phone_numbers_parser.
PhoneFormField(
decoration: const InputDecoration(
labelText: 'Phone number',
hintText: 'Enter your phone number',
),
textInputAction: TextInputAction.next,
autofillHints: const [AutofillHints.telephoneNumber],
validator: (value) {
if (value == null || value.isEmpty) return 'Enter a phone number';
return null;
},
onChanged: (value) {
debugPrint(value); // Example: +15551234567
},
)
You can pass an existing international number as the initial value:
PhoneFormField(
initialValue: '+5511999999999',
decoration: const InputDecoration(labelText: 'Phone'),
)
When the initial value is parseable and its country is allowed, the field opens directly in phone-entry mode with the matching country selected.
Rendering countries and flags #
Use CountryFlag when you only need a flag:
const CountryFlag(
isoCode: 'BR',
size: 24,
borderRadius: BorderRadius.all(Radius.circular(4)),
)
Use CountryWidget when you need the localized country name with the flag:
const CountryWidget(
iso: 'ES',
flagSize: 18,
)
CountryWidget also reads from CountryBloc, so make sure the bloc is
available in the widget tree.
Localization #
Widgets use Localizations.localeOf(context) by default. You can override the
locale when a field needs to render in a specific language:
CountryFormField(
locale: 'es-MX',
decoration: const InputDecoration(labelText: 'País'),
)
Locale values can be language-only (es) or region-specific (es_MX,
es-MX, pt_BR, pt-BR). The lookup tries the full locale, then the language
code, then English, then the first non-empty available value.
You can also customize labels with a builder:
CountryFormField(
countryLabelBuilder: (context, country) {
return country.localizedName('pt-BR');
},
)
For app-specific empty states, pass emptyBuilder.
Styling #
Most visual customization is intentionally grouped into
CountryPhoneFieldStyle:
const countryPhoneStyle = CountryPhoneFieldStyle(
overlayMaxHeight: 260,
overlayBorderRadius: BorderRadius.all(Radius.circular(18)),
overlayElevation: 10,
overlayPadding: EdgeInsets.all(8),
itemPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 14),
itemBorderRadius: BorderRadius.all(Radius.circular(14)),
flagSize: 24,
selectedFlagSize: 20,
flagFit: BoxFit.cover,
);
CountryFormField(
style: countryPhoneStyle,
)
For deeper customization, replace the country item or selected-country button:
PhoneFormField(
countryItemBuilder: (context, country, selected) {
return ListTile(
leading: CountryFlag(isoCode: country.iso2, size: 22),
title: Text(country.localizedName('es')),
trailing: Text(country.phoneCode),
selected: selected,
);
},
selectedCountryButtonBuilder: (context, country, onPressed) {
return TextButton.icon(
onPressed: onPressed,
icon: CountryFlag(isoCode: country.iso2),
label: Text(country.phoneCode),
);
},
)
Working with the catalog #
You can use the catalog directly through the datasource/use case stack:
final bloc = CountryBloc();
await bloc.fetchCountries();
final countries = bloc.countries;
final unitedStates = countries.firstWhere((country) => country.iso2 == 'US');
CountryBloc keeps the loaded countries in memory. Calling fetchCountries()
again will reuse the current list unless force: true is passed internally by
refreshCountries().
API notes #
CountryEntityis immutable, extendsEquatable, and includescopyWith.CountryModelextendsCountryEntityand providesfromJson,fromEntity, andtoJson.CountryModel.fromJsonacceptsphoneCodeorphone_codeand normalizes ISO codes to uppercase.- Phone formatting and parsing are delegated to
phone_numbers_parser. - The package is UI-framework friendly: use the widgets directly or keep the domain/data classes for app-specific wrappers.
Development #
Run the local checks before publishing:
flutter analyze
flutter test
flutter pub publish --dry-run
License #
MIT License. See LICENSE.