【pub地址 】 【github地址】
dependencies: flutter_star: $lastVersion 一、描述目标: 使用canvas手工打造,一个完美的星星评分组件。
---->[StarScore 星星显示组件]---- [1] 比如显示4.2: 会有5颗星, 前四颗填满,后一刻填充20% StarScore 为 Stateless组件,仅负责显示的需求 ---->[CustomRating 星星评分组件]---- [2] 可指定最大值,也就是显示多少个星星 [3] 点击时会改变状态,进行评分,支持半星评分 [4] 支持评分回调 ---->[StarWidget组件]---- [5]. 可定义星星的显示进度情况 0% ~ 100 % 无死角 [6]. 可定义星星的角数 [7]. 可定义星星的颜色、大小 二 、StarScore分数展示组件
名称
类型
功能
备注
默认
score
double
分数
-
0
star
Star
见 第四点
星星属性配置
Star()
tail
Widget
尾部的组件
-
null
StarScore( score: 4.8, star: Star( fillColor: Colors.tealAccent, emptyColor: Colors.grey.withAlpha(88)), tail: Column( children: <Widget>[ Text("综合评分"), Text("4.8"), ], ), ), 三 、CustomRating评分组件
名称
类型
功能
备注
默认
max
int
最大星星数
-
5
score
double
分数
-
0
star
Star
见 第四点
星星属性配置
Star()
onRating
Fluction(double)
点击回调
@required
null
1.最简使用CustomRating(onRating: (s) { print(s); }), 2.可高度定制CustomRating( max: 6, score: 3.0, star: Star( num: 12, fillColor: Colors.orangeAccent, fat: 0.6, emptyColor: Colors.grey.withAlpha(88)), onRating: (s) { print(s); }), 四 、Star星星组件 : 高度可定制的配置类
名称
类型
功能
备注
默认
progress
double
填充的进度
[0,1]
0.0
num
int
星星的角数
大于3
5
fat
double
星星的胖瘦
(0,1]
0.5
emptyColor
Color
星星的色
-
Colors.grey
fillColor
Color
星星的填充色
-
Colors.yellow
size
double
星星的大小
-
20
1. 进度填充:progress2. 星星的角数:num3. 星星的胖瘦:fat4. 星星的颜色:fillColor和emptyColor展示结束,下面进入正文
一 、如何自定义绘制的组件1.分析组件的需求,抽离出需要配置的属性class Star { final int num; final double progress; final Color emptyColor; final Color fillColor; final double size; final double fat; const Star({this.progress = 0, this.fat = 0.5, this.fillColor = Colors.yellow, this.emptyColor = Colors.grey, this.num = 5, this.size = 25}); } 2. 创建好画板准备开画class _StarPainter extends CustomPainter { Star star; Paint _paint; Paint _filePaint; Path _path; double _radius; _StarPainter(this.star) { _paint = Paint() ..color = (star.emptyColor) ..isAntiAlias = true; _filePaint = Paint() ..color = (star.fillColor); _path = Path(); _radius = star.size / 2.0; } @override void paint(Canvas canvas, Size size) { //TODO 绘制 } @override bool shouldRepaint(CustomPainter oldDelegate) { return true; } } 3.开画如果说StarWidget是评分组件的基础,那么绘制的路径就是星星的灵魂 下面的nStarPath是绘制n角星路径的核心方法
Path nStarPath(int num, double R, double r, {dx = 0, dy = 0, rotate = 0}) { _path.reset(); //重置路径 double perRad = 2 * pi / num; //每份的角度 double radA = perRad / 2 / 2 + rotate; //a角 double radB = 2 * pi / (num - 1) / 2 - radA / 2 + radA + rotate; //起始b角 _path.moveTo(cos(radA) * R + dx, -sin(radA) * R + dy); //移动到起点 for (int i = 0; i < num; i++) { //循环生成点,路径连至 _path.lineTo( cos(radA + perRad * i) * R + dx, -sin(radA + perRad * i) * R + dy); _path.lineTo( cos(radB + perRad * i) * r + dx, -sin(radB + perRad * i) * r + dy); } _path.close(); return _path; }在初始化的时候为路径赋值
class _StarPainter extends CustomPainter { ... _StarPainter(this.star) { ... _path = Path(); _radius = star.size / 2.0; nStarPath(star.num, _radius, _radius * star.fat); }绘制也非常简单,其中有个进度问题,可以先画背景的星星, 再画一个填充的星星,再用canvas.clipRect进行裁剪即可。
@override void paint(Canvas canvas, Size size) { canvas.translate(_radius, _radius); canvas.drawPath(_path, _paint); canvas.clipRect(Rect.fromLTRB( -_radius, -_radius, _radius * 2 * star.progress - _radius, _radius)); canvas.drawPath(_path, _filePaint); } 4.自定义组件将画板放入CustomPaint中即可
class StarWidget extends StatelessWidget { final Star star; StarWidget({this.star = const Star()}); @override Widget build(BuildContext context) { return Container( width: star.size, height: star.size, child: CustomPaint( painter: _StarPainter(star), ), ); } }这就是星星组件的所有代码,也不超过百行。
二 、StarScore的实现该组件的目的是显示评分,可以精确的显示百分进度 其实也没啥,仅是用几个StarWidget拼起来而已,代码也就下面一丢丢
class StarScore extends StatelessWidget { final Star star; final double score; final Widget tail; StarScore({this.star = const Star(), this.score, this.tail}); @override Widget build(BuildContext context) { var li = <StarWidget>[]; int count = score.floor(); for (int i = 0; i < count; i++) { li.add(StarWidget(star: star.copyWith(progress: 1.0))); } if (score - count > 0) { li.add(StarWidget(star: star.copyWith(progress: score - count))); } return Wrap( crossAxisAlignment: WrapCrossAlignment.center, children: [ ...li, SizedBox( width: 10, ), if (tail!=null) tail ], ); } } 三 、StarScore的实现由于点击需要自己响应进行状态改变,所以使用StatefulWidget 最核心的是GestureDetector进行触点的获取并计算出当前值。其中对.5进行处理,以及越界的处理。
class CustomRating extends StatefulWidget { final int max; final Star star; final double score; final Function(double) onRating; CustomRating( {this.max = 5, this.score = 0, this.star = const Star(), @required this.onRating}) : assert(score <= max); @override _CustomRatingState createState() => _CustomRatingState(); } class _CustomRatingState extends State<CustomRating> { double _score; @override void initState() { _score = widget.score; super.initState(); } @override Widget build(BuildContext context) { var li = <StarWidget>[]; int count = _score.floor(); //满星 for (int i = 0; i < count; i++) { li.add(StarWidget(star: widget.star.copyWith(progress: 1.0))); } if (_score != widget.max.toDouble()) li.add(StarWidget( star: widget.star.copyWith(progress: _score - count))); //不满星 var empty = widget.max - count - 1; // 空星 for (int i = 0; i < empty; i++) { li.add(StarWidget(star: widget.star.copyWith(progress: 0))); } return GestureDetector( onTapDown: (d) { setState(() { _score = d.localPosition.dx / widget.star.size; if (_score - _score.floor() > 0.5) { _score = _score.floor() + 1.0; } else { _score = _score.floor() + 0.5; } if (_score >= widget.max.toDouble()) { _score = widget.max.toDouble(); } widget.onRating(_score); }); }, child: Wrap( children: li, ), ); } } 复制代码四. 发布到pub1.配置需要在pubspec.yaml进行一些配置
name 是名称 description 是描述 60 ~ 180 之间,太短或太长会扣分 version 版本 author 作者信息,会报warning 但我就想写 homepage 主页 ---->[pubspec.yaml]---- name: flutter_star description: You can create a star easily and decide how many angle or color of the star, even the fat and progress of the star. version: 0.1.2 author: 张风捷特烈<1981462002@qq.com> homepage: https://juejin.im/user/5b42c0656fb9a04fe727eb37/collections 2.最好写个example不然会扣分
它会在这里,给使用者看
3.发布到pubflutter packages pub publish --server=https://pub.dartlang.org然后需要权限验证,记得全部复制在浏览器打开,不用在控制台点链接,由于控制台的换行而导致url不全。
然后就看你的网给不给力了。flutter_star 欢迎使用
---来自腾讯云社区的---张风捷特烈
微信扫一扫打赏
支付宝扫一扫打赏