Flutter —— 自定义星级评价控件

2020-11-19  本文已影响0人  刘铁崧

效果:



使用:

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;//尺寸不同在重新裁剪
  }
}
上一篇 下一篇

猜你喜欢

热点阅读