star.dart 2.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import 'package:flutter/material.dart';
  2. class HTStarRating extends StatefulWidget {
  3. final double rating; // 当前分数
  4. final double maxRating; // 满分
  5. final int count; // 总共几颗心
  6. final double size; // 星星大小
  7. final Color defaultColor;
  8. final Color selectedColor;
  9. final Widget unselectedImage;
  10. final Widget selectedImage;
  11. HTStarRating({
  12. required this.rating, // 必填
  13. //选填, 初始默认值
  14. this.maxRating = 10,
  15. this.count = 5,
  16. this.size = 30,
  17. this.defaultColor = Colors.grey,
  18. this.selectedColor = Colors.red,
  19. Widget? unselectedImage,
  20. Widget? selectedImage,
  21. }) : unselectedImage = unselectedImage ??
  22. Icon(Icons.star_border, color: defaultColor, size: size),
  23. selectedImage =
  24. selectedImage ?? Icon(Icons.star, color: selectedColor, size: size);
  25. @override
  26. _HTStarRatingState createState() => _HTStarRatingState();
  27. }
  28. class _HTStarRatingState extends State<HTStarRating> {
  29. @override
  30. Widget build(BuildContext context) {
  31. return Stack(
  32. children: <Widget>[
  33. Row(mainAxisSize: MainAxisSize.min, children: buildDefaultStar()),
  34. Row(mainAxisSize: MainAxisSize.min, children: buildSelectedStar())
  35. ],
  36. );
  37. }
  38. /*
  39. * 创建默认的星星
  40. * */
  41. List<Widget> buildDefaultStar() {
  42. return List.generate(widget.count, (index) {
  43. return widget.unselectedImage;
  44. });
  45. }
  46. /*
  47. * 创建选中的星星
  48. * */
  49. List<Widget> buildSelectedStar() {
  50. // 创建stats
  51. List<Widget> starts = [];
  52. final star = widget.selectedImage;
  53. //构建满的start
  54. double oneValue = widget.maxRating / widget.count;
  55. int entireCount = (widget.rating / oneValue).floor(); //.floor() 向下取整
  56. for (var i = 0; i < entireCount; i++) {
  57. starts.add(star);
  58. }
  59. //构建部分start
  60. double leftWidth = ((widget.rating / oneValue) - entireCount) * widget.size;
  61. final halfStar = ClipRect(clipper: HTStartClipper(leftWidth), child: star);
  62. starts.add(halfStar);
  63. // 防止传入参数大于总分
  64. if (starts.length > widget.count) {
  65. return starts.sublist(0, widget.count);
  66. }
  67. return starts;
  68. }
  69. }
  70. /*
  71. * 切割
  72. * */
  73. class HTStartClipper extends CustomClipper<Rect> {
  74. double width;
  75. HTStartClipper(this.width);
  76. @override
  77. Rect getClip(Size size) {
  78. return Rect.fromLTRB(0, 0, width, size.height);
  79. }
  80. @override
  81. bool shouldReclip(HTStartClipper oldClipper) {
  82. return oldClipper.width != this.width;
  83. }
  84. }