country_search 1.0.3
country_search: ^1.0.3 copied to clipboard
A beautiful and customizable country picker widget for Flutter with multi-language support.
Country Search #
A beautiful and customizable country picker widget for Flutter with multi-language support.
Features #
- 🌍 200+ Countries: Comprehensive list of countries with flags and ISO codes
- 🌐 Multi-language Support: Built-in support for English, Spanish, French, and Russian
- 🎨 Customizable UI: Dark theme with modern design
- 🔍 Smart Search: Search by country name or code with priority ranking
- 📱 Responsive: Works on all screen sizes
- ⚡ Lightweight: Minimal dependencies
- 🎯 Fully Localized: All UI text is localized (labels, placeholders, titles)
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
country_search: ^1.0.0
Usage #
Basic Usage #
import 'package:country_search/country_search.dart';
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Country? selectedCountry;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
child: CountryPicker(
selectedCountry: selectedCountry,
onCountrySelected: (Country country) {
setState(() {
selectedCountry = country;
});
debugPrint('Selected: ${country.flag} ${country.code}');
},
),
),
);
}
}
Custom Labels #
CountryPicker(
selectedCountry: selectedCountry,
onCountrySelected: (Country country) {
setState(() {
selectedCountry = country;
});
},
labelText: 'Choose your country',
hintText: 'Select a country',
)
Multi-language Setup #
To enable multi-language support, add the localizations to your app:
import 'package:country_search/country_search.dart';
MaterialApp(
localizationsDelegates: [
// ... other delegates
CountryLocalizations.delegate,
],
supportedLocales: [
const Locale('en'),
const Locale('es'),
const Locale('fr'),
const Locale('ru'),
],
// ... rest of your app
)
Language Switching Example #
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('en');
void _changeLanguage(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
localizationsDelegates: [
CountryLocalizations.delegate,
// ... other delegates
],
supportedLocales: [
const Locale('en'),
const Locale('es'),
const Locale('fr'),
const Locale('ru'),
],
home: MyHomePage(onLanguageChanged: _changeLanguage),
);
}
}
API Reference #
CountryPicker Widget #
| Parameter | Type | Required | Description |
|---|---|---|---|
selectedCountry |
Country? |
No | Currently selected country |
onCountrySelected |
Function(Country) |
Yes | Callback when country is selected |
labelText |
String? |
No | Custom label text (overrides localized text) |
hintText |
String? |
No | Custom hint text (overrides localized text) |
Country Model #
class Country {
final String code; // ISO country code (e.g., 'US', 'RU')
final String flag; // Country flag emoji (e.g., '🇺🇸', '🇷🇺')
}
CountryData Utility #
// Get country by code
Country? country = CountryData.getCountryByCode('US');
// Get sorted countries for current language
List<Country> sortedCountries = CountryData.getSortedCountries(
(code) => CountryLocalizations.of(context).getCountryName(code)
);
// Search countries with smart ranking
List<Country> results = CountryData.searchCountries(
'russia',
(code) => CountryLocalizations.of(context).getCountryName(code)
);
Localization Methods #
// Get localized country name
String countryName = CountryLocalizations.of(context).getCountryName('US');
// Get all country names for current language
Map<String, String> allNames = CountryLocalizations.of(context).allCountryNames;
// Get localized UI text
String selectText = CountryLocalizations.of(context).selectCountry;
String searchText = CountryLocalizations.of(context).searchCountry;
String hintText = CountryLocalizations.of(context).selectYourCountry;
Supported Languages #
- 🇺🇸 English (en) - "Select Country", "Search country...", "Select your country"
- 🇪🇸 Spanish (es) - "Seleccionar país", "Buscar país...", "Selecciona tu país"
- 🇫🇷 French (fr) - "Sélectionner un pays", "Rechercher un pays...", "Sélectionnez votre pays"
- 🇷🇺 Russian (ru) - "Выберите страну", "Поиск страны...", "Выберите вашу страну"
Features in Detail #
Smart Search Algorithm #
The search functionality prioritizes results in this order:
- Exact matches - Country name or code exactly matches query
- Starts with - Country name or code starts with query
- Contains - Country name or code contains query
Localization Support #
- All UI text is automatically localized based on app locale
- Country names are sorted alphabetically in the current language
- Search works in the current language
- Custom labels can override localized text
Responsive Design #
- Adapts to different screen sizes
- Modal bottom sheet with draggable height
- Optimized for mobile and desktop
Complete Example #
import 'package:flutter/material.dart';
import 'package:country_search/country_search.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('en');
void _changeLanguage(Locale locale) {
setState(() {
_locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Country Picker Demo',
theme: ThemeData.dark(),
locale: _locale,
localizationsDelegates: [
CountryLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: [
const Locale('en'),
const Locale('es'),
const Locale('fr'),
const Locale('ru'),
],
home: MyHomePage(onLanguageChanged: _changeLanguage, currentLocale: _locale),
);
}
}
class MyHomePage extends StatefulWidget {
final Function(Locale) onLanguageChanged;
final Locale currentLocale;
const MyHomePage({
required this.onLanguageChanged,
required this.currentLocale,
});
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Country? selectedCountry;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Country Picker Demo'),
actions: [
PopupMenuButton<Locale>(
onSelected: widget.onLanguageChanged,
itemBuilder: (context) => [
const PopupMenuItem(
value: Locale('en'),
child: Text('🇺🇸 English'),
),
const PopupMenuItem(
value: Locale('es'),
child: Text('🇪🇸 Español'),
),
const PopupMenuItem(
value: Locale('fr'),
child: Text('🇫🇷 Français'),
),
const PopupMenuItem(
value: Locale('ru'),
child: Text('🇷🇺 Русский'),
),
],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(_getLanguageFlag(widget.currentLocale)),
const SizedBox(width: 8),
Text(_getLanguageName(widget.currentLocale)),
],
),
),
),
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
CountryPicker(
selectedCountry: selectedCountry,
onCountrySelected: (Country country) {
setState(() {
selectedCountry = country;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Selected: ${country.flag} ${country.code}'),
backgroundColor: Colors.green,
),
);
},
),
const SizedBox(height: 20),
if (selectedCountry != null)
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white.withAlpha((0.1 * 255).toInt()),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.white24),
),
child: Row(
children: [
Text(
selectedCountry!.flag,
style: const TextStyle(fontSize: 32),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
selectedCountry!.code,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
CountryLocalizations.of(context).getCountryName(selectedCountry!.code),
style: const TextStyle(
fontSize: 14,
color: Colors.white70,
),
),
],
),
),
],
),
),
],
),
),
);
}
String _getLanguageFlag(Locale locale) {
switch (locale.languageCode) {
case 'en': return '🇺🇸';
case 'es': return '🇪🇸';
case 'fr': return '🇫🇷';
case 'ru': return '🇷🇺';
default: return '🇺🇸';
}
}
String _getLanguageName(Locale locale) {
switch (locale.languageCode) {
case 'en': return 'English';
case 'es': return 'Español';
case 'fr': return 'Français';
case 'ru': return 'Русский';
default: return 'English';
}
}
}
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.