如何正确创建评级星条?

azi*_*iza 6 dart flutter

我正在尝试为用户评分创建一个星形栏,以下图片来自Play商店以说明我想要实现的目标:

在此输入图像描述

我已经能够实现以下功能,正如您所看到的那样功能正常,但是当我查看我的代码时,我觉得必须有一个更聪明的方法来实现它,而真正令人烦恼的部分是IconButton命中区域正在被转移一点点,所以当你触摸实际的星星它没有注册为触摸事件(即:你必须瞄准高于按钮所在的位置,以便你的触摸被注册,这会导致一个糟糕的用户体验)当我点击任何一个星星时,你可以通过关注飞溅效果来检查我的意思:

在此输入图像描述

var _myColorOne = Colors.grey;
  var _myColorTwo = Colors.grey;
  var _myColorThree = Colors.grey;
  var _myColorFour = Colors.grey;
  var _myColorFive = Colors.grey;


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
     appBar: new AppBar(
       title: new Text("My Rating"),
     ),
      body:  new Center(
        child: new Container(
          height: 10.0,
          width: 500.0,
          child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new IconButton(icon: new Icon(Icons.star),
                  onPressed: ()=>setState((){
                    _myColorOne=Colors.orange;
                    _myColorTwo=null;
                    _myColorThree=null;
                    _myColorFour=null;
                    _myColorFive=null;
                }),color: _myColorOne,),
                new IconButton(icon: new Icon(Icons.star),
                  onPressed: ()=>setState((){
                    _myColorOne=Colors.orange;
                    _myColorTwo=Colors.orange;
                    _myColorThree=Colors.grey;
                    _myColorFour=Colors.grey;
                    _myColorFive=Colors.grey;
                }),color: _myColorTwo,),
                new IconButton(icon: new Icon(Icons.star), onPressed: ()=>setState((){
                  _myColorOne=Colors.orange;
                  _myColorTwo=Colors.orange;
                  _myColorThree=Colors.orange;
                  _myColorFour=Colors.grey;
                  _myColorFive=Colors.grey;
                }),color: _myColorThree,),
                new IconButton(icon: new Icon(Icons.star), onPressed: ()=>setState((){
                  _myColorOne=Colors.orange;
                  _myColorTwo=Colors.orange;
                  _myColorThree=Colors.orange;
                  _myColorFour=Colors.orange;
                  _myColorFive=Colors.grey;
                }),color: _myColorFour,),
                new IconButton(icon: new Icon(Icons.star), onPressed: ()=>setState((){
                  _myColorOne=Colors.orange;
                  _myColorTwo=Colors.orange;
                  _myColorThree=Colors.orange;
                  _myColorFour=Colors.orange;
                  _myColorFive=Colors.orange;
                }),color: _myColorFive,),
              ],

          ),
        ),
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

那么这里更好的方法是什么?

Rém*_*let 17

重复和填充太多了!咄

无论如何,我就是这样做的.简单,可重复使用.你可以使用和不使用点击(没有点击禁用涟漪效果).半星也是.如果没有指定颜色,则使用填充星形的原色.

在此输入图像描述

typedef void RatingChangeCallback(double rating);

class StarRating extends StatelessWidget {
  final int starCount;
  final double rating;
  final RatingChangeCallback onRatingChanged;
  final Color color;

  StarRating({this.starCount = 5, this.rating = .0, this.onRatingChanged, this.color});

  Widget buildStar(BuildContext context, int index) {
    Icon icon;
    if (index >= rating) {
      icon = new Icon(
        Icons.star_border,
        color: Theme.of(context).buttonColor,
      );
    }
    else if (index > rating - 1 && index < rating) {
      icon = new Icon(
        Icons.star_half,
        color: color ?? Theme.of(context).primaryColor,
      );
    } else {
      icon = new Icon(
        Icons.star,
        color: color ?? Theme.of(context).primaryColor,
      );
    }
    return new InkResponse(
      onTap: onRatingChanged == null ? null : () => onRatingChanged(index + 1.0),
      child: icon,
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Row(children: new List.generate(starCount, (index) => buildStar(context, index)));
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

class Test extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<Test> {
  double rating = 3.5;

  @override
  Widget build(BuildContext context) {
    return new StarRating(
      rating: rating,
      onRatingChanged: (rating) => setState(() => this.rating = rating),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Yas*_*epa 8

pub.dev上有一个包可以轻松做到这一点。

检查这个 - https://pub.dev/packages/smooth_star_rating

完整示例

 import 'package:flutter/material.dart';
 import 'package:smooth_star_rating/smooth_star_rating.dart';

 void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
 @override
  _MyAppState createState() => _MyAppState();
}

 class _MyAppState extends State<MyApp> {
 var rating = 0.0;

 @override
 Widget build(BuildContext context) {
    return MaterialApp(
    title: 'Rating bar demo',
    theme: ThemeData(
    primarySwatch: Colors.green,
  ),
  debugShowCheckedModeBanner: false,
  home: Scaffold(
    body: Center(
        child: SmoothStarRating(
      rating: rating,
      size: 45,
      starCount: 5,
      onRatingChanged: (value) {
        setState(() {
          rating = value;
        });
      },
      )),
    ),
  );
 }
}
Run Code Online (Sandbox Code Playgroud)

演示

在此处输入图片说明


Yuc*_*ong 6

另一个很好的选择是使用这个库:flutter_ rating_bar。它实现良好、优雅且易于配置。

https://pub.dev/packages/flutter_ rating_bar

例子:

RatingBar(
   initialRating: 3,
   minRating: 1,
   direction: Axis.horizontal,
   allowHalfRating: true,
   itemCount: 5,
   itemPadding: EdgeInsets.symmetric(horizontal: 4.0),
   itemBuilder: (context, _) => Icon(
     Icons.star,
     color: Colors.amber,
   ),
   onRatingUpdate: (rating) {
     print(rating);
   },
);
Run Code Online (Sandbox Code Playgroud)