Merge pull request #1 from imtoori/master

Merge
This commit is contained in:
simon
2020-05-06 03:00:24 -04:00
committed by GitHub
9 changed files with 147 additions and 61 deletions

View File

@@ -1,3 +1,31 @@
## 1.3.12+1
- Fix Cayman Islands code
## 1.3.12
- Allow to edit dialog textStyle
## 1.3.11
- Fix initialization
## 1.3.9
- Add hideSearch property
- Add spanish support
## 1.3.8
- Expose state to let use a key to open the dialog
- Add dialog size config
- Remove customList and fix countryFilter
- Fix filtering with localization
## 1.3.7
- Add `customList` property

View File

@@ -55,7 +55,8 @@ Just add the `CountryLocalizations.delegate` in the list of your app delegates
supportedLocales: [
Locale('en'),
Locale('it'),
Locale('en'),
Locale('fr'),
Locale('es'),
],
localizationsDelegates: [
CountryLocalizations.delegate,
@@ -64,6 +65,36 @@ Just add the `CountryLocalizations.delegate` in the list of your app delegates
],
```
## Customization
Here is a list of properties available to customize your widget:
| Name | Type | Description |
|-----|-----|------|
|onChanged| ValueChanged<CountryCode> | callback invoked when the selection changes |
|onInit| ValueChanged<CountryCode> | callback invoked during initialization of the widget |
|initialSelection| String | used to set the initial selected value |
|favorite| List<String> | used to populate the favorite country list |
|textStyle| TextStyle | TextStyle applied to the widget button |
|padding| EdgeInsetsGeometry | the padding applied to the button |
|showCountryOnly| bool | true if you want to see only the countries in the selection dialog |
|searchDecoration| InputDecoration | decoration applied to the TextField search widget |
|searchStyle| TextStyle | style applied to the TextField search widget text |
|emptySearchBuilder| WidgetBuilder | use this to customize the widget used when the search returns 0 elements |
|builder| Function(CountryCode) | use this to build a custom widget instead of the default FlatButton |
|enabled| bool | set to false to disable the widget |
|textOverflow| TextOverflow | the button text overflow behaviour |
|dialogSize| Size | the size of the selection dialog |
|countryFilter| List<String> | uses a list of strings to filter a sublist of countries |
|showOnlyCountryWhenClosed| bool | if true it'll show only the country |
|alignLeft| bool | aligns the flag and the Text to the left |
|showFlag| bool | shows the flag everywhere |
|showFlagMain| bool | shows the flag only when closed |
|showFlagDialog| bool | shows the flag only in dialog |
|flagWidth| double | the width of the flags |
|comparator| Comparator<CountryCode> | use this to sort the countries in the selection dialog |
|hideSearch| bool | if true the search feature will be disabled |
## Contributions
Contributions of any kind are more than welcome! Feel free to fork and improve country_code_picker in any way you want, make a pull request, or open an issue.

View File

@@ -11,18 +11,14 @@ class MyApp extends StatefulWidget {
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
supportedLocales: [
Locale('en'),
Locale('it'),
Locale('en'),
Locale('fr'),
Locale('es'),
],
localizationsDelegates: [
CountryLocalizations.delegate,
@@ -43,11 +39,12 @@ class _MyAppState extends State<MyApp> {
initialSelection: 'IT',
favorite: ['+39', 'FR'],
showFlag: false,
customList: ['IT', 'FR'],
countryFilter: ['IT', 'FR'],
showFlagDialog: true,
comparator: (a, b) => b.name.compareTo(a.name),
//Get the country information relevant to the initial selection
onInit: (code) => print("${code.name} ${code.dialCode}"),
onInit: (code) =>
print("on init ${code.name} ${code.dialCode}"),
),
SizedBox(
width: 400,
@@ -57,6 +54,7 @@ class _MyAppState extends State<MyApp> {
child: CountryCodePicker(
onChanged: print,
initialSelection: 'TF',
hideSearch: true,
showCountryOnly: true,
showOnlyCountryWhenClosed: true,
alignLeft: true,
@@ -72,7 +70,7 @@ class _MyAppState extends State<MyApp> {
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CountryCodePicker(
onChanged: print,
onChanged: (e) => print(e.toLongString()),
initialSelection: 'TF',
showCountryOnly: true,
showOnlyCountryWhenClosed: true,

View File

@@ -59,13 +59,9 @@ class CountryCode {
@override
String toString() => "$dialCode";
String toLongString([BuildContext context]) =>
"$dialCode ${toCountryStringOnly(context)}";
String toLongString() => "$dialCode ${toCountryStringOnly()}";
String toCountryStringOnly([BuildContext context]) {
if (context != null) {
return CountryLocalizations.of(context)?.translate(code) ?? name;
}
String toCountryStringOnly() {
return '$name';
}
}

View File

@@ -17,13 +17,17 @@ class CountryCodePicker extends StatefulWidget {
final bool showCountryOnly;
final InputDecoration searchDecoration;
final TextStyle searchStyle;
final TextStyle dialogTextStyle;
final WidgetBuilder emptySearchBuilder;
final Function(CountryCode) builder;
final bool enabled;
final TextOverflow textOverflow;
/// the size of the selection dialog
final Size dialogSize;
/// used to customize the country list
final List<String> customList;
final List<String> countryFilter;
/// shows the name of the country instead of the dialcode
final bool showOnlyCountryWhenClosed;
@@ -42,26 +46,26 @@ class CountryCodePicker extends StatefulWidget {
final bool showFlagDialog;
/// contains the country codes to load only the specified countries.
final List<String> countryFilter;
/// Width of the flag images
final double flagWidth;
/// Use this property to change the order of the options
final Comparator<CountryCode> comparator;
/// Set to true if you want to hide the search part
final bool hideSearch;
CountryCodePicker({
this.onChanged,
this.onInit,
this.initialSelection,
this.favorite = const [],
this.countryFilter = const [],
this.textStyle,
this.padding = const EdgeInsets.all(0.0),
this.showCountryOnly = false,
this.searchDecoration = const InputDecoration(),
this.searchStyle,
this.dialogTextStyle,
this.emptySearchBuilder,
this.showOnlyCountryWhenClosed = false,
this.alignLeft = false,
@@ -73,8 +77,11 @@ class CountryCodePicker extends StatefulWidget {
this.enabled = true,
this.textOverflow = TextOverflow.ellipsis,
this.comparator,
this.customList,
});
this.countryFilter,
this.hideSearch = false,
this.dialogSize,
Key key,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
@@ -87,42 +94,40 @@ class CountryCodePicker extends StatefulWidget {
elements.sort(comparator);
}
if (customList != null) {
if (countryFilter != null && countryFilter.isNotEmpty) {
final uppercaseCustomList =
countryFilter.map((c) => c.toUpperCase()).toList();
elements = elements
.where((c) =>
customList.contains(c.code) ||
customList.contains(c.name) ||
customList.contains(c.dialCode))
uppercaseCustomList.contains(c.code) ||
uppercaseCustomList.contains(c.name) ||
uppercaseCustomList.contains(c.dialCode))
.toList();
}
if (countryFilter.length > 0) {
elements = elements.where((c) => countryFilter.contains(c.code)).toList();
}
return _CountryCodePickerState(elements);
return CountryCodePickerState(elements);
}
}
class _CountryCodePickerState extends State<CountryCodePicker> {
class CountryCodePickerState extends State<CountryCodePicker> {
CountryCode selectedItem;
List<CountryCode> elements = [];
List<CountryCode> favoriteElements = [];
_CountryCodePickerState(this.elements);
CountryCodePickerState(this.elements);
@override
Widget build(BuildContext context) {
Widget _widget;
if (widget.builder != null)
_widget = InkWell(
onTap: _showSelectionDialog,
child: widget.builder(selectedItem.localize(context)),
onTap: showCountryCodePickerDialog,
child: widget.builder(selectedItem),
);
else {
_widget = FlatButton(
padding: widget.padding,
onPressed: widget.enabled ? _showSelectionDialog : null,
onPressed: widget.enabled ? showCountryCodePickerDialog : null,
child: Flex(
direction: Axis.horizontal,
mainAxisSize: MainAxisSize.min,
@@ -146,7 +151,7 @@ class _CountryCodePickerState extends State<CountryCodePicker> {
fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose,
child: Text(
widget.showOnlyCountryWhenClosed
? selectedItem.toCountryStringOnly(context)
? selectedItem.toCountryStringOnly()
: selectedItem.toString(),
style: widget.textStyle ?? Theme.of(context).textTheme.button,
overflow: widget.textOverflow,
@@ -159,49 +164,63 @@ class _CountryCodePickerState extends State<CountryCodePicker> {
return _widget;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
this.elements = elements.map((e) => e.localize(context)).toList();
}
@override
void didUpdateWidget(CountryCodePicker oldWidget) {
super.didUpdateWidget(oldWidget);
_onInit(selectedItem);
if (oldWidget.initialSelection != widget.initialSelection) {
if (widget.initialSelection != null) {
selectedItem = elements.firstWhere(
(e) =>
(e.code.toUpperCase() ==
widget.initialSelection.toUpperCase()) ||
(e.dialCode == widget.initialSelection.toString()),
(e.dialCode == widget.initialSelection) ||
(e.name.toUpperCase() == widget.initialSelection.toUpperCase()),
orElse: () => elements[0]);
} else {
selectedItem = elements[0];
}
_onInit(selectedItem);
}
}
@override
initState() {
void initState() {
super.initState();
if (widget.initialSelection != null) {
selectedItem = elements.firstWhere(
(e) =>
(e.code.toUpperCase() == widget.initialSelection.toUpperCase()) ||
(e.dialCode == widget.initialSelection.toString()),
(e.dialCode == widget.initialSelection) ||
(e.name.toUpperCase() == widget.initialSelection.toUpperCase()),
orElse: () => elements[0]);
} else {
selectedItem = elements[0];
}
_onInit(selectedItem);
favoriteElements = elements
.where((e) =>
widget.favorite.firstWhere(
(f) => e.code == f.toUpperCase() || e.dialCode == f.toString(),
(f) =>
e.code.toUpperCase() == f.toUpperCase() ||
e.dialCode == f ||
e.name.toUpperCase() == f.toUpperCase(),
orElse: () => null) !=
null)
.toList();
super.initState();
}
void _showSelectionDialog() {
void showCountryCodePickerDialog() {
showDialog(
context: context,
builder: (_) => SelectionDialog(
@@ -211,8 +230,11 @@ class _CountryCodePickerState extends State<CountryCodePicker> {
emptySearchBuilder: widget.emptySearchBuilder,
searchDecoration: widget.searchDecoration,
searchStyle: widget.searchStyle,
textStyle: widget.dialogTextStyle,
showFlag: widget.showFlag || (widget.showFlagDialog == true),
flagWidth: widget.flagWidth,
size: widget.dialogSize,
hideSearch: widget.hideSearch,
),
).then((e) {
if (e != null) {
@@ -227,13 +249,13 @@ class _CountryCodePickerState extends State<CountryCodePicker> {
void _publishSelection(CountryCode e) {
if (widget.onChanged != null) {
widget.onChanged(e.localize(context));
widget.onChanged(e);
}
}
void _onInit(CountryCode e) {
if (widget.onInit != null) {
widget.onInit(e.localize(context));
widget.onInit(e);
}
}
}

View File

@@ -202,7 +202,7 @@ List<Map<String, String>> codes = [
{
"name": "Cayman Islands",
"code": "KY",
"dial_code": "+ 345",
"dial_code": "+1345",
},
{
"name": "Ködörösêse tî Bêafrîka",

View File

@@ -48,6 +48,7 @@ class _CountryLocalizationsDelegate
'en',
'it',
'fr',
'es',
].contains(locale.languageCode);
}

View File

@@ -7,9 +7,12 @@ class SelectionDialog extends StatefulWidget {
final bool showCountryOnly;
final InputDecoration searchDecoration;
final TextStyle searchStyle;
final TextStyle textStyle;
final WidgetBuilder emptySearchBuilder;
final bool showFlag;
final double flagWidth;
final Size size;
final bool hideSearch;
/// elements passed as favorite
final List<CountryCode> favoriteElements;
@@ -22,8 +25,11 @@ class SelectionDialog extends StatefulWidget {
this.emptySearchBuilder,
InputDecoration searchDecoration = const InputDecoration(),
this.searchStyle,
this.textStyle,
this.showFlag,
this.flagWidth = 32,
this.size,
this.hideSearch = false,
}) : assert(searchDecoration != null, 'searchDecoration must not be null!'),
this.searchDecoration =
searchDecoration.copyWith(prefixIcon: Icon(Icons.search)),
@@ -52,20 +58,22 @@ class _SelectionDialogState extends State<SelectionDialog> {
),
onPressed: () => Navigator.pop(context),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextField(
style: widget.searchStyle,
decoration: widget.searchDecoration,
onChanged: _filterElements,
if (!widget.hideSearch)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextField(
style: widget.searchStyle,
decoration: widget.searchDecoration,
onChanged: _filterElements,
),
),
),
],
),
children: [
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.7,
width: widget.size?.width ?? MediaQuery.of(context).size.width,
height:
widget.size?.height ?? MediaQuery.of(context).size.height * 0.7,
child: ListView(
children: [
widget.favoriteElements.isEmpty
@@ -123,9 +131,10 @@ class _SelectionDialogState extends State<SelectionDialog> {
flex: 4,
child: Text(
widget.showCountryOnly
? e.toCountryStringOnly(context)
: e.toLongString(context),
? e.toCountryStringOnly()
: e.toLongString(),
overflow: TextOverflow.fade,
style: widget.textStyle,
),
),
],

View File

@@ -1,6 +1,6 @@
name: country_code_picker
description: A flutter package for showing a country code selector. In addition it gives the possibility to select a list of favorites countries, as well as to search using a simple searchbox
version: 1.3.7
version: 1.3.12+1
homepage: https://github.com/imtoori/CountryCodePicker
environment:
@@ -16,3 +16,4 @@ flutter:
- packages/country_code_picker/i18n/en.json
- packages/country_code_picker/i18n/it.json
- packages/country_code_picker/i18n/fr.json
- packages/country_code_picker/i18n/es.json