11import  'package:flutter/material.dart' ;
22import  'package:chips_choice/chips_choice.dart' ;
3+ import  'package:async/async.dart' ;
4+ import  'package:dio/dio.dart' ;
35
46void  main () =>  runApp (MyApp ());
57
@@ -34,6 +36,22 @@ class _MyHomePageState extends State<MyHomePage> {
3436    'Science' ,
3537  ];
3638
39+   String  user;
40+   final  usersMemoizer =  AsyncMemoizer <List <ChipsChoiceOption <String >>>();
41+ 
42+   Future <List <ChipsChoiceOption <String >>> getUsers () async  {
43+     String  url =  "https://randomuser.me/api/?inc=gender,name,nat,picture,email&results=25" ;
44+     Response  res =  await  Dio ().get (url);
45+     return  ChipsChoiceOption .listFrom <String , dynamic >(
46+       source:  res.data['results' ],
47+       value:  (index, item) =>  item['email' ],
48+       label:  (index, item) =>  item['name' ]['first' ] +  ' '  +  item['name' ]['last' ],
49+       avatar:  (index, item) =>  CircleAvatar (
50+         backgroundImage:  NetworkImage (item['picture' ]['thumbnail' ]),
51+       ),
52+     )..insert (0 , ChipsChoiceOption <String >(value:  'all' , label:  'All' ));
53+   }
54+ 
3755  @override 
3856  Widget  build (BuildContext  context) {
3957    return  Scaffold (
@@ -100,7 +118,7 @@ class _MyHomePageState extends State<MyHomePage> {
100118            ),
101119          ),
102120          Content (
103-             title:  'Disabled Choice item ' ,
121+             title:  'Disabled Choice Item ' ,
104122            child:  ChipsChoice <int >.single (
105123              value:  tag,
106124              options:  ChipsChoiceOption .listFrom <int , String >(
@@ -114,7 +132,7 @@ class _MyHomePageState extends State<MyHomePage> {
114132            ),
115133          ),
116134          Content (
117-             title:  'Hidden Choice item ' ,
135+             title:  'Hidden Choice Item ' ,
118136            child:  ChipsChoice <String >.multiple (
119137              value:  tags,
120138              options:  ChipsChoiceOption .listFrom <String , String >(
@@ -128,19 +146,146 @@ class _MyHomePageState extends State<MyHomePage> {
128146            ),
129147          ),
130148          Content (
131-             title:  'Custom Choice item' ,
149+             title:  'Append an Item to Options' ,
150+             child:  ChipsChoice <int >.single (
151+               value:  tag,
152+               options:  ChipsChoiceOption .listFrom <int , String >(
153+                 source:  options,
154+                 value:  (i, v) =>  i,
155+                 label:  (i, v) =>  v,
156+               )..insert (0 , ChipsChoiceOption <int >(value:  - 1 , label:  'All' )),
157+               onChanged:  (val) =>  setState (() =>  tag =  val),
158+             ),
159+           ),
160+           Content (
161+             title:  'Selected without Checkmark and Brightness Dark' ,
162+             child:  ChipsChoice <int >.single (
163+               value:  tag,
164+               onChanged:  (val) =>  setState (() =>  tag =  val),
165+               options:  ChipsChoiceOption .listFrom <int , String >(
166+                 source:  options,
167+                 value:  (i, v) =>  i,
168+                 label:  (i, v) =>  v,
169+               )..insert (0 , ChipsChoiceOption <int >(value:  - 1 , label:  'All' )),
170+               itemConfig:  const  ChipsChoiceItemConfig (
171+                 showCheckmark:  false ,
172+                 selectedBrightness:  Brightness .dark,
173+                 // unselectedBrightness: Brightness.dark, 
174+               ),
175+             ),
176+           ),
177+           Content (
178+             title:  'Async Options and Brightness Dark' ,
179+             child:  FutureBuilder <List <ChipsChoiceOption <String >>>(
180+               initialData:  [],
181+               future:  usersMemoizer.runOnce (getUsers),
182+               builder:  (context, snapshot) {
183+                 if  (snapshot.connectionState ==  ConnectionState .waiting) {
184+                   return  Padding (
185+                     padding:  const  EdgeInsets .all (20 ),
186+                     child:  Center (
187+                       child:  SizedBox (
188+                         width:  20 ,
189+                         height:  20 ,
190+                         child:  CircularProgressIndicator (
191+                           strokeWidth:  2 ,
192+                         )
193+                       ),
194+                     ),
195+                   );
196+                 } else  {
197+                   if  (! snapshot.hasError) {
198+                     return  ChipsChoice <String >.single (
199+                       value:  user,
200+                       options:  snapshot.data,
201+                       onChanged:  (val) =>  setState (() =>  user =  val),
202+                       itemConfig:  ChipsChoiceItemConfig (
203+                         selectedColor:  Colors .green,
204+                         unselectedColor:  Colors .blueGrey,
205+                         selectedBrightness:  Brightness .dark,
206+                         unselectedBrightness:  Brightness .dark,
207+                         showCheckmark:  false ,
208+                       ),
209+                     );
210+                   } else  {
211+                     return  Container (
212+                       padding:  const  EdgeInsets .all (25 ),
213+                       child:  Text (
214+                         snapshot.error.toString (),
215+                         style:  const  TextStyle (color:  Colors .red),
216+                       ),
217+                     );
218+                   }
219+                 }
220+               },
221+             ),
222+           ),
223+           Content (
224+             title:  'Works with FormField and Validator' ,
225+             child:  FormField <List <String >>(
226+               autovalidate:  true ,
227+               initialValue:  tags,
228+               validator:  (value) {
229+                 if  (value.isEmpty) {
230+                   return  'Please select some categories' ;
231+                 }
232+                 if  (value.length >  5 ) {
233+                   return  "Can't select more than 5 categories" ;
234+                 }
235+                 return  null ;
236+               },
237+               builder:  (state) {
238+                 return  Column (
239+                   children:  < Widget > [
240+                     Container (
241+                       alignment:  Alignment .centerLeft,
242+                       child:  ChipsChoice <String >.multiple (
243+                         value:  state.value,
244+                         options:  ChipsChoiceOption .listFrom <String , String >(
245+                           source:  options,
246+                           value:  (i, v) =>  v,
247+                           label:  (i, v) =>  v,
248+                         ),
249+                         onChanged:  (val) =>  state.didChange (val),
250+                         itemConfig:  ChipsChoiceItemConfig (
251+                           selectedColor:  Colors .indigo,
252+                           selectedBrightness:  Brightness .dark,
253+                           unselectedColor:  Colors .indigo,
254+                           unselectedBorderOpacity:  .3 ,
255+                         ),
256+                         isWrapped:  true ,
257+                       ),
258+                     ),
259+                     Container (
260+                       padding:  EdgeInsets .fromLTRB (15 , 0 , 15 , 15 ),
261+                       alignment:  Alignment .centerLeft,
262+                       child:  Text (
263+                         state.errorText ??  state.value.length.toString () +  '/5 selected' ,
264+                         style:  TextStyle (
265+                           color:  state.hasError
266+                             ?  Colors .redAccent
267+                             :  Colors .green
268+                         ),
269+                       )
270+                     )
271+                   ],
272+                 );
273+               },
274+             ),
275+           ),
276+           Content (
277+             title:  'Custom Choice Widget' ,
132278            child:  ChipsChoice <String >.multiple (
133279              value:  tags,
134280              options:  ChipsChoiceOption .listFrom <String , String >(
135281                source:  options,
136282                value:  (i, v) =>  v,
137283                label:  (i, v) =>  v,
138284              ),
139-               itemBuilder:  (item, selected, onSelect ) {
140-                 return  CustomChip (item.value, item. label, selected, onSelect );
285+               itemBuilder:  (item, selected, select ) {
286+                 return  CustomChip (item.label, selected, select );
141287              },
142288              onChanged:  (val) =>  setState (() =>  tags =  val),
143-               isWrapped:  true ,
144289            ),
145290          ),
146291        ],
@@ -149,15 +294,13 @@ class _MyHomePageState extends State<MyHomePage> {
149294  }
150295}
151296
152- class  CustomChip < T >  extends  StatelessWidget  {
297+ class  CustomChip  extends  StatelessWidget  {
153298
154-   final  T  value;
155299  final  String  label;
156300  final  bool  selected;
157-   final  Function (T  value,  bool  selected) onSelect;
301+   final  Function (bool  selected) onSelect;
158302
159303  CustomChip (
160-     this .value,
161304    this .label,
162305    this .selected,
163306    this .onSelect,
@@ -167,28 +310,50 @@ class CustomChip<T> extends StatelessWidget {
167310  @override 
168311  Widget  build (BuildContext  context) {
169312    return  AnimatedContainer (
170-       margin:  EdgeInsets .symmetric (vertical:  5 ),
313+       height:  100 ,
314+       width:  70 ,
315+       margin:  EdgeInsets .symmetric (
316+         vertical:  15 ,
317+         horizontal:  5 ,
318+       ),
171319      duration:  Duration (milliseconds:  300 ),
172320      decoration:  BoxDecoration (
173321        color:  selected ?  Colors .green :  Colors .transparent,
322+         borderRadius:  BorderRadius .circular (15 ),
174323        border:  Border .all (
175324          color:  selected ?  Colors .green :  Colors .grey,
176325          width:  1 ,
177326        ),
178327      ),
179328      child:  InkWell (
180-         onTap:  () =>  onSelect (value, ! selected),
181-         child:  Padding (
182-           padding:  EdgeInsets .symmetric (
183-             vertical:  7 ,
184-             horizontal:  9 ,
185-           ),
186-           child:  Text (
187-             label,
188-             style:  TextStyle (
189-               color:  selected ?  Colors .white :  Colors .black45,
329+         onTap:  () =>  onSelect (! selected),
330+         child:  Stack (
331+           alignment:  Alignment .center,
332+           children:  < Widget > [
333+             Visibility (
334+               visible:  selected,
335+               child:  Icon (
336+                 Icons .check_circle_outline,
337+                 color:  Colors .white,
338+                 size:  32 ,
339+               )
190340            ),
191-           ),
341+             Positioned (
342+               left:  9 ,
343+               right:  9 ,
344+               bottom:  7 ,
345+               child:  Container (
346+                 child:  Text (
347+                   label,
348+                   maxLines:  1 ,
349+                   overflow:  TextOverflow .ellipsis,
350+                   style:  TextStyle (
351+                     color:  selected ?  Colors .white :  Colors .black45,
352+                   ),
353+                 ),
354+               ),
355+             ),
356+           ],
192357        ),
193358      ),
194359    );
@@ -244,7 +409,7 @@ void _about(BuildContext context) {
244409          ListTile (
245410            title:  Text (
246411              'chips_choice' ,
247-               style:  Theme .of (context).textTheme.headline.merge ( TextStyle ( color:  Colors .black87) ),
412+               style:  Theme .of (context).textTheme.headline.copyWith ( color:  Colors .black87),
248413            ),
249414            subtitle:  Text ('by davigmacode' ),
250415            trailing:  IconButton (
@@ -261,13 +426,13 @@ void _about(BuildContext context) {
261426                children:  < Widget > [
262427                  Text (
263428                    'Easy way to provide a single or multiple choice chips.' ,
264-                     style:  Theme .of (context).textTheme.body1.merge ( TextStyle ( color:  Colors .black54) ),
429+                     style:  Theme .of (context).textTheme.body1.copyWith ( color:  Colors .black54),
265430                  ),
266431                  Container (height:  15 ),
267432                ],
268433              ),
269434            ),
270-           )
435+           ), 
271436        ],
272437      ),
273438    ),
0 commit comments