Let’s learn how to create a star rating widget in flutter. This widget would be responsible to creating stars on the UI.
It should be fed the data from the backend. But for now we will use hard coded value.
RatingBar class, checks for whether the number of stars are integer or with floating point number.
The parameter rating could take any value like integer or number with decimal points.
Whatever is it first we turn the rating into a closest first smallest integer by using dart function floor().
And then we take rest rating number again and turn it into closest first biggest integer by using ceil().
int realNumber = rating.floor();
int partNumber = ((rating - realNumber) * 10).ceil();
We save our star in _starList List. It saves custom and non-custom star shapes.
For non-custom star shapes, we have used ClipRect with CustomClipper.
void main() async {
runApp(MyApp( ));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Colors.blue,
fontFamily: "Lato",
),
home: Scaffold(
backgroundColor: Colors.red,
body: Center(
child: RatingBar(
rating: 4,
ratingCount: 12,
),
),
),
);
}
}
class RatingBar extends StatelessWidget {
final double rating;
final double size;
final int ratingCount;
RatingBar({required this.rating, required this.ratingCount, this.size = 18});
@override
Widget build(BuildContext context) {
List<Widget> _starList = [];
int realNumber = rating.floor();
int partNumber = ((rating - realNumber) * 10).ceil();
for (int i = 0; i < 5; i++) {
if (i < realNumber) {
_starList.add(Icon(Icons.star, color: Theme.of(context).primaryColor, size: size));
} else if (i == realNumber) {
_starList.add(SizedBox(
height: size,
width: size,
child: Stack(
fit: StackFit.expand,
children: [
Icon(Icons.star, color: Theme.of(context).primaryColor, size: size),
ClipRect(
clipper: _Clipper(part: partNumber),
child: Icon(Icons.star, color: Colors.grey, size: size),
)
],
),
));
} else {
_starList.add(Icon(Icons.star, color: Colors.grey, size: size));
}
}
ratingCount != null ? _starList.add(Padding(
padding: EdgeInsets.only(left:10),
child: Text('($ratingCount)', style: TextStyle(
fontSize: size*0.8, color: Theme.of(context).disabledColor)
)),
) : SizedBox();
return Row(
mainAxisSize: MainAxisSize.min,
children: _starList,
);
}
}
class _Clipper extends CustomClipper<Rect> {
final int part;
_Clipper({required this.part});
@override
Rect getClip(Size size) {
return Rect.fromLTRB(
(size.width / 10) * part,
0.0,
size.width,
size.height,
);
}
@override
bool shouldReclip(CustomClipper<Rect> oldClipper) => true;
}
CustomClipper makes it more dynamic star rating widget. Because of CustomClipper you may stars like 3.5 or 4.5 or 5.