Flutter —— 自定义星级评价控件
2020-11-19 本文已影响0人
刘铁崧
效果:

使用:
- 必传参数rating:分值,其他为可选参数
- 可以自行传入UI样式
YStarRating(rating: 2,starNumbers: 5)
封装:
class CYStarRating extends StatefulWidget {
final double rating;
final double totalRating;
final int starNumbers;
final double starSize;
final Color defaultColor;
final Color selectedColor;
// 使用自定义图片
final Widget defaultImg;
final Widget selectedImg;
CYStarRating({
@required this.rating,
this.totalRating = 10,
this.starNumbers = 5,
this.starSize = 30,
this.defaultColor = const Color(0xffbbbbbb),
this.selectedColor = const Color(0xffff0000),
Widget defaultImg,
Widget selectedImg
}) : defaultImg = defaultImg ?? Icon(Icons.star_border,size: starSize,color: defaultColor),
selectedImg = selectedImg ?? Icon(Icons.star,color: selectedColor,size: starSize);
@override
_CYStarRatingState createState() => _CYStarRatingState();
}
class _CYStarRatingState extends State<CYStarRating> {
@override
Widget build(BuildContext context) {
return Stack(
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: defaultStarList(),
),
Row(
mainAxisSize: MainAxisSize.min,
children: selectedStarList(),
)
],
);
}
// 默认星
List<Widget> defaultStarList(){
return List.generate(widget.starNumbers, (index){
return widget.defaultImg;
});
}
// 选中星
List<Widget> selectedStarList(){
List<Widget> stars = [];
// 全星
final fullStar = widget.selectedImg;//满星UI
double singleStarRate = widget.totalRating / widget.starNumbers;//单星分值
int starCount = (widget.rating/singleStarRate).floor();// 实星个数(向下取整)
for (var i = 0;i<starCount;i++){
stars.add(fullStar);
}
// 半星
double halfStarWith = ((widget.rating / singleStarRate) - starCount) * widget.starSize;//计算半星裁剪尺寸
final halfStar = ClipRect(child: fullStar,clipper: CYStarClipper(halfStarWith));//半星UI(使用自定义裁剪方法裁剪)
stars.add(halfStar);//添加半星
return stars.length > widget.starNumbers ? stars.sublist(0,widget.starNumbers) : stars;
}
}
// 将全星裁剪为半星 <Rect>l类型,使用矩形裁剪
class CYStarClipper extends CustomClipper<Rect> {
double width;
CYStarClipper(this.width);
@override
Rect getClip(Size size) {//具体裁剪对象
return Rect.fromLTRB(0, 0, width, size.height);
}
@override
bool shouldReclip(CYStarClipper oldClipper) {// 重新裁剪
return oldClipper.width != this.width;//尺寸不同在重新裁剪
}
}