【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 ~