custom_language_picker 0.0.3
custom_language_picker: ^0.0.3 copied to clipboard
A customizable language picker for Flutter with modern UI, storage support, and emoji flags.
import 'package:custom_language_picker/custom_language_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp(key: Key('app')));
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Language Picker Example',
theme: ThemeData(
primarySwatch: Colors.blue,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const MyHomePage(title: 'Custom Language Picker Example'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Language? _selectedDropdownLanguage;
Language? _selectedDialogLanguage;
Language? _selectedCupertinoLanguage;
List<Language> _favoriteLanguages = [];
@override
void initState() {
super.initState();
_selectedDropdownLanguage = Languages.getLanguageByCode(LanguageCode.ko);
_selectedDialogLanguage = Languages.getLanguageByCode(LanguageCode.ko);
_selectedCupertinoLanguage = Languages.getLanguageByCode(LanguageCode.ko);
_favoriteLanguages = [
Languages.getLanguageByCode(LanguageCode.en),
Languages.getLanguageByCode(LanguageCode.fr),
Languages.getLanguageByCode(LanguageCode.de),
];
}
Widget _buildDropdownItem(Language language, {bool? isFavorite, VoidCallback? onFavoriteToggle}) {
return Row(
children: <Widget>[
Text(language.flagEmoji),
const SizedBox(width: 8.0),
Expanded(child: Text("${language.name} (${language.isoCode})")),
if (isFavorite != null)
IconButton(
icon: Icon(
isFavorite ? Icons.star : Icons.star_border,
size: 20,
color: isFavorite ? Colors.amber : Colors.grey,
),
onPressed: onFavoriteToggle,
splashRadius: 20,
padding: EdgeInsets.zero,
constraints: const BoxConstraints(
minWidth: 20,
minHeight: 20,
),
),
],
);
}
Widget _buildDialogItem(Language language, {bool? isFavorite, VoidCallback? onFavoriteToggle}) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: Row(
children: <Widget>[
Text(language.flagEmoji, style: const TextStyle(fontSize: 24)),
const SizedBox(width: 12.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(language.name),
const SizedBox(height: 4.0),
Text(
language.nativeName,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
),
if (isFavorite != null)
IconButton(
icon: Icon(
isFavorite ? Icons.star : Icons.star_border,
color: isFavorite ? Colors.amber : Colors.grey,
),
onPressed: onFavoriteToggle,
),
],
),
);
}
void _openLanguagePickerDialog() => showDialog(
context: context,
builder: (context) => Theme(
data: Theme.of(context).copyWith(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.pink),
),
child: CustomLanguagePickerDialog(
// Title customization
titleText: 'Select your language',
titlePadding: const EdgeInsets.all(16.0),
headerBackgroundColor: Colors.pink,
headerTextColor: Colors.white,
headerShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 6,
offset: const Offset(0, 3),
),
],
closeIcon: Icons.close_rounded,
closeIconColor: Colors.white,
// Dialog appearance
dialogBorderRadius: 16.0,
dialogElevation: 10.0,
dialogBackgroundColor: Colors.white,
// Search field customization
isSearchable: true,
searchHintText: 'Search...',
searchBackgroundColor: Colors.grey.shade50,
searchBorderColor: Colors.grey.shade300,
searchFocusedBorderColor: Colors.pinkAccent,
searchIconColor: Colors.pinkAccent,
searchClearIconColor: Colors.grey,
searchTextColor: Colors.black87,
searchCursorColor: Colors.pinkAccent,
searchBorderRadius: 12.0,
searchInputDecoration: const InputDecoration(
hintText: 'Search...',
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
),
// Favorites section customization
showFavoritesSection: true,
favoritesTitle: 'My Favorites',
favoritesTitleColor: Colors.pinkAccent,
favoritesIconColor: Colors.pinkAccent,
favoritesChipBackgroundColor: Colors.pink.shade50,
favoritesChipTextColor: Colors.pink.shade800,
favoritesChipAvatarBackgroundColor: Colors.pink.shade100,
favoritesChipDeleteIconColor: Colors.pinkAccent,
// Item customization
selectedItemBackgroundColor: Colors.pink.shade50,
selectedItemTextColor: Colors.pink.shade800,
selectedItemBorderColor: Colors.pinkAccent,
selectedItemBorderWidth: 4.0,
favoriteIconActiveColor: Colors.amber,
favoriteIconInactiveColor: Colors.grey.shade400,
// Divider customization
showDividers: true,
dividerColor: Colors.grey.shade200,
// No results customization
noResultsTextColor: Colors.grey.shade600,
noResultsIconColor: Colors.grey.shade300,
// Search highlight customization
searchHighlightColor: Colors.pinkAccent,
searchHighlightBackgroundColor: Colors.pink.shade50,
// Native name display
showNativeNames: true,
// Data and callbacks
initialFavorites: _favoriteLanguages,
onValuePicked: (Language language) {
setState(() {
_selectedDialogLanguage = language;
print('Selected language: ${language.name}');
print('ISO code: ${language.isoCode}');
});
},
onFavoritesChanged: (List<Language> favorites) {
setState(() {
_favoriteLanguages = favorites;
print('Favorites updated: ${favorites.map((e) => e.name).join(', ')}');
});
},
itemBuilder: _buildDialogItem,
),
),
);
void _openCupertinoLanguagePicker() => showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) {
return CustomLanguagePickerCupertino(
pickerSheetHeight: 250.0,
initialFavorites: _favoriteLanguages,
onValuePicked: (Language language) {
setState(() {
_selectedCupertinoLanguage = language;
print('Selected language: ${language.name}');
print('ISO code: ${language.isoCode}');
});
},
onFavoritesChanged: (List<Language> favorites) {
setState(() {
_favoriteLanguages = favorites;
print('Favorites updated: ${favorites.map((e) => e.name).join(', ')}');
});
},
);
},
);
Widget _buildCupertinoSelectedItem(Language? language) {
if (language == null) return const Text('Select a language');
return Row(
children: <Widget>[
Text(language.flagEmoji, style: const TextStyle(fontSize: 24)),
const SizedBox(width: 12.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(language.name),
Text(
language.nativeName,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
),
const Icon(Icons.arrow_drop_down),
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const SizedBox(height: 24),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Language Dropdown:',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
CustomLanguagePickerDropdown(
initialValue: _selectedDropdownLanguage,
itemBuilder: _buildDropdownItem,
initialFavorites: _favoriteLanguages,
onValuePicked: (Language language) {
setState(() {
_selectedDropdownLanguage = language;
print('Selected language: ${language.name}');
print('ISO code: ${language.isoCode}');
});
},
onFavoritesChanged: (List<Language> favorites) {
setState(() {
_favoriteLanguages = favorites;
print('Favorites updated: ${favorites.map((e) => e.name).join(', ')}');
});
},
isSearchable: true,
showNativeNames: true,
showFavoritesFirst: true,
searchHintText: 'Search languages...',
favoritesSectionLabel: 'Favorites',
dropdownBackgroundColor: Colors.white,
dropdownTextColor: Colors.black87,
dropdownBorderColor: Colors.grey.shade300,
dropdownIconColor: Colors.grey.shade700,
searchHighlightColor: Colors.blue,
searchHighlightBackgroundColor: Colors.blue.withOpacity(0.1),
searchFieldTextColor: Colors.black87,
searchFieldBackgroundColor: Colors.grey.shade50,
searchFieldFocusedBorderColor: Colors.blue,
searchFieldHintColor: Colors.grey,
searchFieldCursorColor: Colors.blue,
selectedItemColor: Colors.blue,
selectedItemBackgroundColor: Colors.blue.withOpacity(0.1),
favoriteIconActiveColor: Colors.amber,
favoriteIconInactiveColor: Colors.grey.shade400,
dropdownOverlayColor: Colors.white,
dropdownOverlayShadowColor: Colors.black26,
dividerColor: Colors.grey.shade200,
favoritesSectionLabelColor: Colors.grey.shade800,
favoritesSectionIconColor: Colors.amber,
favoritesSectionBackgroundColor: Colors.grey.shade50,
noResultsTextColor: Colors.grey.shade700,
noResultsIconColor: Colors.grey.shade400,
dropdownOverlayElevation: 8.0,
dropdownBorderRadius: 8.0,
dropdownOverlayBorderRadius: 12.0,
dropdownBorderWidth: 1.0,
),
],
),
),
const Divider(),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Language Dialog:',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: _selectedDialogLanguage != null
? Row(
children: [
Text(
_selectedDialogLanguage!.flagEmoji,
style: const TextStyle(fontSize: 24),
),
const SizedBox(width: 12),
Text(_selectedDialogLanguage!.name),
],
)
: const Text('No language selected'),
),
),
),
const SizedBox(width: 16),
ElevatedButton(
onPressed: _openLanguagePickerDialog,
child: const Text("Open Dialog"),
),
],
),
],
),
),
const Divider(),
// Cupertino example
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Cupertino Picker:',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Card(
child: InkWell(
onTap: _openCupertinoLanguagePicker,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: _buildCupertinoSelectedItem(_selectedCupertinoLanguage),
),
),
),
],
),
),
const Divider(),
// Favorites section
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Your Favorite Languages:',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Wrap(
spacing: 8,
runSpacing: 8,
children: _favoriteLanguages.map((language) {
return Chip(
avatar: Text(language.flagEmoji),
label: Text(language.name),
deleteIcon: const Icon(Icons.close, size: 16),
onDeleted: () {
setState(() {
_favoriteLanguages.removeWhere(
(lang) => lang.code == language.code);
});
},
);
}).toList(),
),
],
),
),
],
),
),
);
}
}