Skip to content

Commit 0ec0386

Browse files
committed
Initial release
1 parent 3915576 commit 0ec0386

File tree

9 files changed

+339
-65
lines changed

9 files changed

+339
-65
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
## [0.0.1] - TODO: Add release date.
1+
## [1.0.0] - 2020-01-24
22

3-
* TODO: Describe initial release.
3+
* Initial release
4+
* Select single or multiple choice
5+
* Display in scrollable or wrapped List
6+
* Customizable choice input
7+
* Build choice option from any List

README.md

Lines changed: 131 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,136 @@
11
# chips_choice
22

3-
A new Flutter package project.
3+
Lite version of [smart_select](https://pub.dev/packages/smart_select) package, zero dependencies, an easy way to provide a single or multiple choice chips.
44

5-
## Getting Started
5+
## Demo
66

7-
This project is a starting point for a Dart
8-
[package](https://flutter.dev/developing-packages/),
9-
a library module containing code that can be shared easily across
10-
multiple Flutter or Dart projects.
7+
### Preview
118

12-
For help getting started with Flutter, view our
13-
[online documentation](https://flutter.dev/docs), which offers tutorials,
14-
samples, guidance on mobile development, and a full API reference.
9+
![Demo Preview](https://github.com/davigmacode/flutter_chips_choice/raw/master/example/art/screencast.gif)
10+
11+
### Download
12+
13+
[![Demo App](https://github.com/davigmacode/flutter_chips_choice/raw/master/example/art/qr-apk.png "ChipsChoice Demo App")](https://github.com/davigmacode/flutter_chips_choice/blob/master/example/art/ChipsChoice.apk?raw=true)
14+
15+
16+
## Features
17+
18+
* Select single or multiple choice
19+
* Display in scrollable or wrapped List
20+
* Customizable choice input
21+
* Build choice option from any List
22+
23+
## Usage
24+
25+
For a complete usage, please see the [example](https://pub.dev/packages/chips_choice#-example-tab-).
26+
27+
To read more about classes and other references used by `chips_choice`, see the [documentation](https://pub.dev/documentation/chips_choice/latest/).
28+
29+
### Single Choice
30+
31+
```
32+
int tag = 1;
33+
List<String> options = [
34+
'News', 'Entertainment', 'Politics',
35+
'Automotive', 'Sports', 'Education',
36+
'Fashion', 'Travel', 'Food', 'Tech',
37+
'Science',
38+
];
39+
40+
// ChipsChoice<T>.single
41+
ChipsChoice<int>.single(
42+
value: tag,
43+
options: ChipsChoiceOption.listFrom<int, String>(
44+
source: options,
45+
value: (i, v) => i,
46+
label: (i, v) => v,
47+
),
48+
onChanged: (val) => setState(() => tag = val),
49+
);
50+
51+
```
52+
53+
### Multiple Choice
54+
55+
```
56+
List<String> tags = [];
57+
List<String> options = [
58+
'News', 'Entertainment', 'Politics',
59+
'Automotive', 'Sports', 'Education',
60+
'Fashion', 'Travel', 'Food', 'Tech',
61+
'Science',
62+
];
63+
64+
// ChipsChoice<T>.multiple
65+
ChipsChoice<String>.multiple(
66+
value: tags,
67+
options: ChipsChoiceOption.listFrom<String, String>(
68+
source: options,
69+
value: (i, v) => v,
70+
label: (i, v) => v,
71+
),
72+
onChanged: (val) => setState(() => tags = val),
73+
);
74+
```
75+
76+
### Build Options List
77+
78+
`options` property is `List<ChipsChoiceOption<T>>`, it can be input directly as in the example below, more info about `ChipsChoiceOption` can be found on the [API Reference](https://pub.dev/documentation/chips_choice/latest/chips_choice/ChipsChoiceOption-class.html)
79+
80+
```
81+
ChipsChoice<T>.single/multiple(
82+
...,
83+
...,
84+
options: <ChipsChoiceOption<int>>[
85+
ChipsChoiceOption<int>(value: 1, label: 'Entertainment'),
86+
ChipsChoiceOption<int>(value: 2, label: 'Education'),
87+
ChipsChoiceOption<int>(value: 3, label: 'Fashion'),
88+
],
89+
);
90+
```
91+
92+
`options` also can be created from any list using helper provided by this package, like the example below
93+
94+
```
95+
List<Map<String, String>> days = [
96+
{ 'value': 'mon', 'title': 'Monday' },
97+
{ 'value': 'tue', 'title': 'Tuesday' },
98+
{ 'value': 'wed', 'title': 'Wednesday' },
99+
{ 'value': 'thu', 'title': 'Thursday' },
100+
{ 'value': 'fri', 'title': 'Friday' },
101+
{ 'value': 'sat', 'title': 'Saturday' },
102+
{ 'value': 'sun', 'title': 'Sunday' },
103+
];
104+
105+
ChipsChoice<T>.single/multiple(
106+
...,
107+
...,
108+
options: ChipsChoiceOption.listFrom<T, Map<String, String>>(
109+
source: days,
110+
value: (index, item) => item['value'],
111+
label: (index, item) => item['title'],
112+
),
113+
);
114+
```
115+
116+
### Scrollable or Wrapped List
117+
118+
```
119+
ChipsChoice<T>.single/multiple(
120+
...,
121+
...,
122+
isWrapped: false/true,
123+
);
124+
```
125+
126+
## License
127+
128+
```
129+
Copyright (c) 2020 Irfan Vigma Taufik
130+
131+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
132+
133+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
134+
135+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
136+
```

example/art/ChipsChoice.apk

6.52 MB
Binary file not shown.

example/art/qr-apk.png

1.67 KB
Loading

example/art/screencast.gif

3.44 MB
Loading

example/lib/main.dart

Lines changed: 114 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ class _MyHomePageState extends State<MyHomePage> {
3939
return Scaffold(
4040
appBar: AppBar(
4141
title: Text('Flutter ChipsChoice'),
42+
actions: <Widget>[
43+
IconButton(
44+
icon: Icon(Icons.help_outline),
45+
onPressed: () => _about(context),
46+
)
47+
],
4248
),
4349
body: ListView(
4450
padding: EdgeInsets.all(5),
@@ -47,7 +53,7 @@ class _MyHomePageState extends State<MyHomePage> {
4753
title: 'Scrollable List Single Choice',
4854
child: ChipsChoice<int>.single(
4955
value: tag,
50-
options: ChipsChoiceOption.listFrom<String, int>(
56+
options: ChipsChoiceOption.listFrom<int, String>(
5157
source: options,
5258
value: (i, v) => i,
5359
label: (i, v) => v,
@@ -71,16 +77,13 @@ class _MyHomePageState extends State<MyHomePage> {
7177
title: 'Wrapped List Single Choice',
7278
child: ChipsChoice<int>.single(
7379
value: tag,
74-
options: ChipsChoiceOption.listFrom<String, int>(
80+
options: ChipsChoiceOption.listFrom<int, String>(
7581
source: options,
7682
value: (i, v) => i,
7783
label: (i, v) => v,
7884
),
7985
onChanged: (val) => setState(() => tag = val),
80-
itemConfig: ChipsChoiceItemConfig(
81-
isWrapped: true,
82-
margin: EdgeInsets.all(0)
83-
),
86+
isWrapped: true,
8487
),
8588
),
8689
Content(
@@ -93,27 +96,21 @@ class _MyHomePageState extends State<MyHomePage> {
9396
label: (i, v) => v,
9497
),
9598
onChanged: (val) => setState(() => tags = val),
96-
itemConfig: ChipsChoiceItemConfig(
97-
isWrapped: true,
98-
margin: EdgeInsets.all(0)
99-
),
99+
isWrapped: true,
100100
),
101101
),
102102
Content(
103103
title: 'Disabled Choice item',
104104
child: ChipsChoice<int>.single(
105105
value: tag,
106-
options: ChipsChoiceOption.listFrom<String, int>(
106+
options: ChipsChoiceOption.listFrom<int, String>(
107107
source: options,
108108
value: (i, v) => i,
109109
label: (i, v) => v,
110110
disabled: (i, v) => [0, 2, 5].contains(i),
111111
),
112112
onChanged: (val) => setState(() => tag = val),
113-
itemConfig: ChipsChoiceItemConfig(
114-
isWrapped: true,
115-
margin: EdgeInsets.all(0)
116-
),
113+
isWrapped: true,
117114
),
118115
),
119116
Content(
@@ -127,10 +124,23 @@ class _MyHomePageState extends State<MyHomePage> {
127124
hidden: (i, v) => ['Science', 'Politics', 'News', 'Tech'].contains(v),
128125
),
129126
onChanged: (val) => setState(() => tags = val),
130-
itemConfig: ChipsChoiceItemConfig(
131-
isWrapped: true,
132-
margin: EdgeInsets.all(0)
127+
isWrapped: true,
128+
),
129+
),
130+
Content(
131+
title: 'Custom Choice item',
132+
child: ChipsChoice<String>.multiple(
133+
value: tags,
134+
options: ChipsChoiceOption.listFrom<String, String>(
135+
source: options,
136+
value: (i, v) => v,
137+
label: (i, v) => v,
133138
),
139+
itemBuilder: (item, selected, onSelect) {
140+
return CustomChip(item.value, item.label, selected, onSelect);
141+
},
142+
onChanged: (val) => setState(() => tags = val),
143+
isWrapped: true,
134144
),
135145
),
136146
],
@@ -139,6 +149,52 @@ class _MyHomePageState extends State<MyHomePage> {
139149
}
140150
}
141151

152+
class CustomChip<T> extends StatelessWidget {
153+
154+
final T value;
155+
final String label;
156+
final bool selected;
157+
final Function(T value, bool selected) onSelect;
158+
159+
CustomChip(
160+
this.value,
161+
this.label,
162+
this.selected,
163+
this.onSelect,
164+
{ Key key }
165+
) : super(key: key);
166+
167+
@override
168+
Widget build(BuildContext context) {
169+
return AnimatedContainer(
170+
margin: EdgeInsets.symmetric(vertical: 5),
171+
duration: Duration(milliseconds: 300),
172+
decoration: BoxDecoration(
173+
color: selected ? Colors.green : Colors.transparent,
174+
border: Border.all(
175+
color: selected ? Colors.green : Colors.grey,
176+
width: 1,
177+
),
178+
),
179+
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,
190+
),
191+
),
192+
),
193+
),
194+
);
195+
}
196+
}
197+
142198
class Content extends StatelessWidget {
143199

144200
final String title;
@@ -177,3 +233,43 @@ class Content extends StatelessWidget {
177233
);
178234
}
179235
}
236+
237+
void _about(BuildContext context) {
238+
showDialog(
239+
context: context,
240+
builder: (_) => Dialog(
241+
child: Column(
242+
mainAxisSize: MainAxisSize.min,
243+
children: <Widget>[
244+
ListTile(
245+
title: Text(
246+
'chips_choice',
247+
style: Theme.of(context).textTheme.headline.merge(TextStyle(color: Colors.black87)),
248+
),
249+
subtitle: Text('by davigmacode'),
250+
trailing: IconButton(
251+
icon: Icon(Icons.close),
252+
onPressed: () => Navigator.pop(context),
253+
),
254+
),
255+
Flexible(
256+
fit: FlexFit.loose,
257+
child: Container(
258+
padding: EdgeInsets.symmetric(horizontal: 15),
259+
child: Column(
260+
mainAxisSize: MainAxisSize.min,
261+
children: <Widget>[
262+
Text(
263+
'Easy way to provide a single or multiple choice chips.',
264+
style: Theme.of(context).textTheme.body1.merge(TextStyle(color: Colors.black54)),
265+
),
266+
Container(height: 15),
267+
],
268+
),
269+
),
270+
)
271+
],
272+
),
273+
),
274+
);
275+
}

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ packages:
4242
path: ".."
4343
relative: true
4444
source: path
45-
version: "0.0.1"
45+
version: "1.0.0"
4646
collection:
4747
dependency: transitive
4848
description:

0 commit comments

Comments
 (0)