/
country_list_view.dart
160 lines (144 loc) · 4.84 KB
/
country_list_view.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import 'package:country_picker/country_picker.dart';
import 'package:country_picker/src/utils.dart';
import 'package:flutter/material.dart';
import 'country.dart';
import 'res/country_codes.dart';
class CountryListView extends StatefulWidget {
/// Called when a country is select.
///
/// The country picker passes the new value to the callback.
final ValueChanged<Country> onSelect;
/// An optional [showPhoneCode] argument can be used to show phone code.
final bool showPhoneCode;
/// An optional [exclude] argument can be used to exclude(remove) one ore more
/// country from the countries list. It takes a list of country code(iso2).
/// Note: Can't provide both [exclude] and [countryFilter]
final List<String> exclude;
/// An optional [countryFilter] argument can be used to filter the
/// list of countries. It takes a list of country code(iso2).
/// Note: Can't provide both [countryFilter] and [exclude]
final List<String> countryFilter;
const CountryListView({
Key key,
@required this.onSelect,
this.exclude,
this.countryFilter,
this.showPhoneCode = false,
}) : assert(onSelect != null),
assert(exclude == null || countryFilter == null,
'Cannot provide both exclude and countryFilter'),
super(key: key);
@override
_CountryListViewState createState() => _CountryListViewState();
}
class _CountryListViewState extends State<CountryListView> {
List<Country> _countryList;
List<Country> _filteredList;
TextEditingController _searchController;
@override
void initState() {
super.initState();
_searchController = TextEditingController();
_countryList =
countryCodes.map((country) => Country.from(json: country)).toList();
if (widget.exclude != null) {
_countryList.removeWhere(
(element) => widget.exclude.contains(element.countryCode));
}
if (widget.countryFilter != null) {
_countryList.removeWhere(
(element) => !widget.countryFilter.contains(element.countryCode));
}
_filteredList = <Country>[];
_filteredList.addAll(_countryList);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
const SizedBox(height: 12),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
child: TextField(
controller: _searchController,
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
prefixIcon: const Icon(Icons.search),
border: OutlineInputBorder(
borderSide: BorderSide(
color: const Color(0xFF8C98A8).withOpacity(0.2),
),
),
),
onChanged: _filterSearchResults,
),
),
Expanded(
child: ListView(
children: _filteredList
.map<Widget>((country) => _listRow(country))
.toList(),
),
),
],
);
}
Widget _listRow(Country country) {
return Material(
// Add Material Widget with transparent color
// so the ripple effect of InkWell will show on tap
color: Colors.transparent,
child: InkWell(
onTap: () {
widget.onSelect(country);
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: Row(
children: <Widget>[
const SizedBox(width: 20),
Text(
Utils.countryCodeToEmoji(country.countryCode),
style: const TextStyle(fontSize: 25),
),
if (widget.showPhoneCode) ...[
const SizedBox(width: 15),
Container(
width: 45,
child: Text(
'+${country.phoneCode}',
style: const TextStyle(fontSize: 16),
),
),
const SizedBox(width: 5),
] else
const SizedBox(width: 15),
Expanded(
child: Text(
CountryLocalizations.of(context)
?.countryName(countryCode: country.countryCode) ??
country.name,
style: const TextStyle(fontSize: 16),
),
)
],
),
),
),
);
}
void _filterSearchResults(String query) {
List<Country> _searchResult = <Country>[];
final CountryLocalizations localizations = CountryLocalizations.of(context);
if (query.isEmpty) {
_searchResult.addAll(_countryList);
} else {
_searchResult = _countryList
.where((c) => c.startsWith(query, localizations))
.toList();
}
setState(() => _filteredList = _searchResult);
}
}