Skip to content

Commit 5f6147a

Browse files
committed
working on on drag rating
1 parent a12a606 commit 5f6147a

6 files changed

Lines changed: 194 additions & 69 deletions

File tree

example/lib/assets/heart.png

8.16 KB
Loading
14 KB
Loading

example/lib/assets/heart_half.png

11.4 KB
Loading

example/lib/main.dart

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ class _MyHomePageState extends State<MyHomePage>
4040
GlobalKey<ScaffoldState>();
4141

4242
TabController tabController;
43+
final _ratingController = TextEditingController();
44+
double _rating = 3.5;
45+
double _userRating = 4.5;
4346

4447
@override
4548
void initState() {
4649
super.initState();
50+
_ratingController.text = '4.5';
4751
tabController = TabController(length: 3, vsync: this);
4852
}
4953

@@ -67,8 +71,6 @@ class _MyHomePageState extends State<MyHomePage>
6771
'Xamarin2',
6872
];
6973

70-
double rating = 3.5;
71-
7274
@override
7375
Widget build(BuildContext context) => Scaffold(
7476
drawer: GFDrawer(
@@ -214,50 +216,99 @@ class _MyHomePageState extends State<MyHomePage>
214216
}),
215217

216218
GFRating(
217-
rating: rating,
218-
// itemSize: 65,
219-
filledIcon: Icons.star,
220-
halfFilledIcon: Icons.star_half,
221-
defaultIcon: Icons.star_border,
222-
itemCount: 5,
223-
allowHalfRating: false,
224-
spacing: 2,
219+
rating: _rating,
220+
itemSize: 50,
221+
// filledIcon: Image.asset(
222+
// 'lib/assets/heart.png',
223+
// height: 50,
224+
// width: 50,
225+
// color: Colors.amber,
226+
// ),
227+
// halfFilledIcon: Image.asset(
228+
// 'lib/assets/heart_half.png',
229+
// height: 50,
230+
// width: 50,
231+
// color: Colors.amber,
232+
// ),
233+
// defaultIcon: Image.asset(
234+
// 'lib/assets/heart_border.png',
235+
// height: 50,
236+
// width: 50,
237+
// color: Colors.amber,
238+
// ),
239+
// allowHalfRating: false,
240+
spacing: 8,
225241
color: Colors.teal,
226242
borderColor: Colors.tealAccent,
227243
onRatingChanged: (value) {
228244
setState(() {
229-
rating = value;
245+
_rating = value;
230246
});
231247
},
232248
),
233249

234-
GFCard(
235-
content: Column(
236-
children: <Widget>[
237-
const GFTypography(
238-
text: 'Toast',
239-
type: GFTypographyType.typo6,
240-
),
241-
const SizedBox(
242-
height: 20,
243-
),
244-
const SizedBox(
245-
height: 20,
246-
),
247-
GFToast(
248-
text: 'Happy New Year',
249-
button: GFButton(
250-
onPressed: () {
251-
print('dfr');
252-
},
253-
text: 'OK',
254-
type: GFButtonType.outline,
255-
color: GFColor.warning,
256-
),
257-
),
258-
],
250+
GFRating(
251+
rating: _userRating,
252+
itemSize: 50,
253+
filledIcon: Image.asset(
254+
'lib/assets/heart.png',
255+
height: 50,
256+
width: 50,
257+
color: Colors.amber,
258+
),
259+
halfFilledIcon: Image.asset(
260+
'lib/assets/heart_half.png',
261+
height: 50,
262+
width: 50,
263+
color: Colors.amber,
264+
),
265+
defaultIcon: Image.asset(
266+
'lib/assets/heart_border.png',
267+
height: 50,
268+
width: 50,
269+
color: Colors.amber,
270+
),
271+
textFormRating: true,
272+
spacing: 8,
273+
color: Colors.teal,
274+
borderColor: Colors.tealAccent,
275+
suffixIcon: MaterialButton(
276+
onPressed: () {
277+
setState(() {
278+
_userRating = double.parse(_ratingController.text ?? '0.0');
279+
});
280+
},
281+
child: const Text('Rate'),
259282
),
260283
),
284+
285+
// GFCard(
286+
// content: Column(
287+
// children: <Widget>[
288+
// const GFTypography(
289+
// text: 'Toast',
290+
// type: GFTypographyType.typo6,
291+
// ),
292+
// const SizedBox(
293+
// height: 20,
294+
// ),
295+
// const SizedBox(
296+
// height: 20,
297+
// ),
298+
// GFToast(
299+
// text: 'Happy New Year',
300+
// button: GFButton(
301+
// onPressed: () {
302+
// print('dfr');
303+
// },
304+
// text: 'OK',
305+
// type: GFButtonType.outline,
306+
// color: GFColor.warning,
307+
// ),
308+
// ),
309+
// ],
310+
// ),
311+
// ),
261312
//
262313
// GFCard(
263314
// content: Column(

example/pubspec.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ flutter:
2828
assets:
2929
- lib/assets/food.jpeg
3030
- lib/assets/img.png
31+
- lib/assets/heart.png
32+
- lib/assets/heart_border.png
33+
- lib/assets/heart_half.png

lib/components/rating/gf_rating.dart

Lines changed: 104 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
22

33
typedef RatingChangeCallback = void Function(double rating);
44

5-
class GFRating extends StatelessWidget {
5+
class GFRating extends StatefulWidget {
66
const GFRating({
77
this.itemCount = 5,
88
this.spacing = 0.0,
@@ -15,6 +15,8 @@ class GFRating extends StatelessWidget {
1515
this.filledIcon,
1616
this.halfFilledIcon,
1717
this.allowHalfRating = true,
18+
this.textFormRating = false,
19+
this.suffixIcon,
1820
}) : assert(rating != null);
1921

2022
/// defines total number of rating items
@@ -33,13 +35,13 @@ class GFRating extends StatelessWidget {
3335
final bool allowHalfRating;
3436

3537
/// defines the items when filled
36-
final IconData filledIcon;
38+
final Widget filledIcon;
3739

3840
/// defines the items when half-filled
39-
final IconData halfFilledIcon;
41+
final Widget halfFilledIcon;
4042

4143
/// defines the default items, when having filledIcon && halfFilledIcon
42-
final IconData defaultIcon;
44+
final Widget defaultIcon;
4345

4446
/// defines the space between items
4547
final double spacing;
@@ -50,54 +52,123 @@ class GFRating extends StatelessWidget {
5052
/// return current rating whenever rating is updated
5153
final RatingChangeCallback onRatingChanged;
5254

55+
final bool textFormRating;
56+
57+
final Widget suffixIcon;
58+
59+
final Controller ratingController;
60+
61+
@override
62+
_GFRatingState createState() => _GFRatingState();
63+
}
64+
65+
class _GFRatingState extends State<GFRating> {
66+
67+
final _ratingController = TextEditingController();
68+
69+
@override
70+
void initState() {
71+
super.initState();
72+
_ratingController.text = '4.5';
73+
}
74+
5375
Widget buildRatingBar(BuildContext context, int index) {
54-
Icon icon;
55-
if (index >= rating) {
56-
icon = Icon(
57-
defaultIcon != null ? defaultIcon : Icons.star_border,
58-
color: borderColor ?? Theme.of(context).primaryColor,
59-
size: itemSize,
76+
Widget icon;
77+
if (index >= widget.rating) {
78+
icon = widget.defaultIcon != null
79+
? widget.defaultIcon
80+
: Icon(
81+
Icons.star_border,
82+
color: widget.borderColor ?? Theme.of(context).primaryColor,
83+
size: widget.itemSize,
6084
);
61-
} else if (index > rating - (allowHalfRating ? 0.5 : 1.0) &&
62-
index <= rating) {
63-
icon = Icon(
64-
halfFilledIcon != null ? halfFilledIcon : Icons.star_half,
65-
color: color ?? Theme.of(context).primaryColor,
66-
size: itemSize,
85+
} else if (!widget.textFormRating
86+
? index > widget.rating - (widget.allowHalfRating ? 0.5 : 1.0) && index < widget.rating
87+
: index + 1 == widget.rating + 0.5) {
88+
icon = widget.halfFilledIcon != null
89+
? widget.halfFilledIcon
90+
: Icon(
91+
Icons.star_half,
92+
color: widget.color ?? Theme.of(context).primaryColor,
93+
size: widget.itemSize,
6794
);
6895
} else {
69-
icon = Icon(
70-
filledIcon != null ? filledIcon : Icons.star,
71-
color: color ?? Theme.of(context).primaryColor,
72-
size: itemSize,
96+
icon = widget.filledIcon != null
97+
? widget.filledIcon
98+
: Icon(
99+
Icons.star,
100+
color: widget.color ?? Theme.of(context).primaryColor,
101+
size: widget.itemSize,
73102
);
74103
}
75104

76105
return GestureDetector(
77106
onTap: () {
78-
if (onRatingChanged != null) {
79-
onRatingChanged(index + 1.0);
107+
if (widget.onRatingChanged != null) {
108+
widget.onRatingChanged(index + 1.0);
80109
}
81110
},
82111
onHorizontalDragUpdate: (dragDetails) {
83112
RenderBox box = context.findRenderObject();
84113
var _pos = box.globalToLocal(dragDetails.globalPosition);
85-
114+
var i = _pos.dx / widget.itemSize;
115+
var newRating = widget.allowHalfRating ? i : i.round().toDouble();
116+
if (newRating > widget.itemCount) {
117+
newRating = widget.itemCount.toDouble();
118+
}
119+
if (newRating < 0) {
120+
newRating = 0.0;
121+
}
122+
if (widget.onRatingChanged != null) {
123+
widget.onRatingChanged(newRating);
124+
}
86125
},
87126
child: icon,
88127
);
89128
}
90129

91-
@override
92-
Widget build(BuildContext context) => Material(
93-
color: Colors.transparent,
94-
child: Wrap(
95-
alignment: WrapAlignment.center,
96-
spacing: spacing,
97-
children: List.generate(
98-
itemCount,
99-
(index) => buildRatingBar(context, index),
130+
// Widget ratingBar(BuildContext context) => ;
131+
132+
133+
@override
134+
Widget build(BuildContext context) => widget.textFormRating ? Column(
135+
children: <Widget>[
136+
Container(
137+
margin: const EdgeInsets.symmetric(vertical: 16),
138+
padding: const EdgeInsets.symmetric(horizontal: 16),
139+
child: TextFormField(
140+
controller: ,
141+
keyboardType: TextInputType.number,
142+
decoration: InputDecoration(
143+
border: const OutlineInputBorder(),
144+
hintText: 'Enter rating',
145+
labelText: 'Enter rating',
146+
suffixIcon: widget.suffixIcon,
147+
),
100148
),
101149
),
102-
);
150+
Material(
151+
color: Colors.transparent,
152+
child: Wrap(
153+
alignment: WrapAlignment.center,
154+
spacing: widget.spacing,
155+
children: List.generate(
156+
widget.itemCount,
157+
(index) => buildRatingBar(context, index),
158+
),
159+
),
160+
)
161+
]
162+
) : Material(
163+
color: Colors.transparent,
164+
child: Wrap(
165+
alignment: WrapAlignment.center,
166+
spacing: widget.spacing,
167+
children: List.generate(
168+
widget.itemCount,
169+
(index) => buildRatingBar(context, index),
170+
),
171+
),
172+
);
103173
}
174+

0 commit comments

Comments
 (0)