您的位置 首页 > 腾讯云社区

【 开源计划 - Flutter组件 】 星星也可以如此闪耀 flutter_star---张风捷特烈

【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 欢迎使用

---来自腾讯云社区的---张风捷特烈

关于作者: 瞎采新闻

这里可以显示个人介绍!这里可以显示个人介绍!

热门文章

留言与评论(共有 0 条评论)
   
验证码: