diff --git a/CHANGELOG.md b/CHANGELOG.md index 319110d..8535eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index e12d084..95d1dad 100644 --- a/README.md +++ b/README.md @@ -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 | callback invoked when the selection changes | +|onInit| ValueChanged | callback invoked during initialization of the widget | +|initialSelection| String | used to set the initial selected value | +|favorite| List | 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 | 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 | 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. diff --git a/example/lib/main.dart b/example/lib/main.dart index c65f5d5..a92be9c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -11,18 +11,14 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - @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 { 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 { child: CountryCodePicker( onChanged: print, initialSelection: 'TF', + hideSearch: true, showCountryOnly: true, showOnlyCountryWhenClosed: true, alignLeft: true, @@ -72,7 +70,7 @@ class _MyAppState extends State { child: Padding( padding: const EdgeInsets.all(8.0), child: CountryCodePicker( - onChanged: print, + onChanged: (e) => print(e.toLongString()), initialSelection: 'TF', showCountryOnly: true, showOnlyCountryWhenClosed: true, diff --git a/lib/country_code.dart b/lib/country_code.dart index 13c1381..627b0c6 100644 --- a/lib/country_code.dart +++ b/lib/country_code.dart @@ -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'; } } diff --git a/lib/country_code_picker.dart b/lib/country_code_picker.dart index 7e491da..3a56eed 100644 --- a/lib/country_code_picker.dart +++ b/lib/country_code_picker.dart @@ -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 customList; + final List 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 countryFilter; - /// Width of the flag images final double flagWidth; /// Use this property to change the order of the options final Comparator 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 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 { +class CountryCodePickerState extends State { CountryCode selectedItem; List elements = []; List 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 { 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 { 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 { 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 { 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); } } } diff --git a/lib/country_codes.dart b/lib/country_codes.dart index 441f66e..826d931 100644 --- a/lib/country_codes.dart +++ b/lib/country_codes.dart @@ -202,7 +202,7 @@ List> codes = [ { "name": "Cayman Islands", "code": "KY", - "dial_code": "+ 345", + "dial_code": "+1345", }, { "name": "Ködörösêse tî Bêafrîka", diff --git a/lib/country_localizations.dart b/lib/country_localizations.dart index 873735d..2705fd8 100644 --- a/lib/country_localizations.dart +++ b/lib/country_localizations.dart @@ -48,6 +48,7 @@ class _CountryLocalizationsDelegate 'en', 'it', 'fr', + 'es', ].contains(locale.languageCode); } diff --git a/lib/selection_dialog.dart b/lib/selection_dialog.dart index eb010c4..3c66f7d 100644 --- a/lib/selection_dialog.dart +++ b/lib/selection_dialog.dart @@ -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 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 { ), 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 { flex: 4, child: Text( widget.showCountryOnly - ? e.toCountryStringOnly(context) - : e.toLongString(context), + ? e.toCountryStringOnly() + : e.toLongString(), overflow: TextOverflow.fade, + style: widget.textStyle, ), ), ], diff --git a/pubspec.yaml b/pubspec.yaml index d44cccf..3fae238 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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