【pub 】 【github 】

dependencies:
  flutter_star: $lastVersion
Copy the code

A, description,

Goal: Handmade with Canvas, a perfect star rating component.

---->[StarScore star display component]---- [1] For example display 4.2: There will be 5 stars, the first four are filled, and the last moment is filled with 20% StarScore for Stateless component, only responsible for display requirements ---->[CustomRating star rating component]---- [2] Maximum value can be specified, How many stars are displayed [3] when clicked, the state will change and the rating will be performed. Support for half star rating [4] Support for rating callback ---->[StarWidget component]---- [5]. Can define the star display progress situation 0% ~ 100% no dead Angle [6]. Can define the number of star angles [7]. Can define the color of the star, sizeCopy the code

Second, the StarScore

Score display component

The name of the type function note The default
score double score 0
star Star seeFourth, Star property configuration Star()
tail Widget Tail component null
StarScore(Score: 4.8, STAR: star (fillColor: Colors. TealAccent, emptyColor: colors.grey.withalpha (88)), tail: The Column (children: < widgets > [Text (" comprehensive score "), Text (" 4.8 "),],),),Copy the code


Third, CustomRating

Grading components

The name of the type function note The default
max int Maximum number of stars 5
score double score 0
star Star seeFourth, Star property configuration Star()
onRating Fluction(double) Click on the callback @required null
1. The simplest use

CustomRating(onRating: (s) {
   print(s);
 }),
Copy the code

2. Highly customizable

CustomRating(Max: 6, Score: rating, star: rating (num: 12, fillColor: Colors. OrangeAccent, FAT: 0.6, emptyColor: Colors.grey.withAlpha(88)), onRating: (s) { print(s); }),Copy the code

Four, Star,

Star components: Highly customizable configuration classes

The name of the type function note The default
progress double Progress of filling [0, 1] 0.0
num int The number of angles of a star More than 3 5
fat double The fat and thin stars (0, 1] 0.5
emptyColor Color The color of stars Colors.grey
fillColor Color The filling color of the stars Colors.yellow
size double The size of a star 20
1. Schedule filling:progress


2. The number of angles of stars:num


3. How thin and fat the stars are:fat


4. Star colors:FillColor and emptyColor

The end of the presentation, now enter the body


1. How to customize the drawing component

1. Analyze component requirements and extract attributes to be configured
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 = color.yellow, this.emptyColor = color.grey, this.num = 5, this.size = 25}); }Copy the code

2. Create a drawing board and prepare to draw
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, @override bool shouldRepaint(CustomPainter oldDelegate) {return true; }}Copy the code

3. Open

If StarWidget is the basis of the scoring component, then the path drawn is the soul of the star

The following nStarPath is the core method for plotting the path of an N-angle star

Path nStarPath(int num, double R, double r, {dx = 0, dy = 0, rotate = 0}) { _path.reset(); Double perRad = 2 * PI/num; Rotate double radA = rotate / 2 + rotate; rotate double radA = rotate / 2 + rotate; // double radB = 2 * PI/(num - 1) / 2 + radA / 2 + radA + rotate; _path.moveto (cos(radA) * R + dx, -sin(radA) * R + dy); For (int I = 0; i < num; 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; }Copy the code

Assign a value to the path during initialization

class _StarPainter extends CustomPainter {
 ...
  _StarPainter(this.star) {
    ...
    _path = Path();
    _radius = star.size / 2.0;
    nStarPath(star.num, _radius, _radius * star.fat);
  }
Copy the code

It’s very easy to draw, and there’s a scheduling problem, you can draw the stars in the background,

Draw a filled star and crop it with 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);
  }
Copy the code

4. Customize components

Place the artboard in 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), ), ); }}Copy the code

That’s all the code for the star component, no more than a hundred lines.


2. Implementation of StarScore

The purpose of this component is to display ratings, which can accurately show percentile progress

It’s nothing, just a couple of starWidgets, and the code is lost

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 ], ); }}Copy the code

Realization of StarScore

Since the click needs to respond to the state change itself, the core of using StatefulWidget is the GestureDetector to obtain the contact and calculate the current value. Where we deal with.5, and we deal with out of bounds.

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; 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, ), ); }}Copy the code

Publish to pub

1. The configuration

Some configuration is required in pubspec.yaml

Name is the name and description is the description of a homepage. If it is too short or too long, it will be penalizedCopy the code
---->[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: Zhang Fong-ji-teoyel <[email protected]> homepage: https://juejin.cn/user/149189281194766Copy the code

2. It is better to write an example

Or you’ll lose points

It’s going to be here for the user to see


3. Post to pub
flutter packages pub publish --server=https://pub.dartlang.org
Copy the code

Then you need to verify permissions, remember to copy all in the browser to open, do not click on the console link, due to the console newline caused by url incomplete.

Then it’s up to you to get the net. Welcome to use flutter_star


The end of the

In addition, I have a Flutter wechat communication group. You are welcome to join and discuss Flutter issues together. I look forward to exchanging ideas with you.

@ZhangFengjietele 2019.02.23 not allowed to transfer

My official number: King of programming contact me – email :[email protected] – wechat :zdl1994328 ~ END ~