如何正确创建评分星条? [英] How to create rating star bar properly?

查看:79
本文介绍了如何正确创建评分星条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to create a star bar for user ratings, the following image is from the play store to illustrate what I am trying to achieve:

我已经能够实现以下功能,正如您所看到的那样,但是当我看一下代码时,我感到就像必须有一种更聪明的方法来做,真正令人烦恼的部分是 IconButton 的点击区域被稍微移了一点,所以当您触摸实际的星星时不会注册为触摸事件(即:您必须将目标对准按钮的定位位置,以便进行触摸注册,这会导致不良的UX),您可以通过留意飞溅来检查我的意思单击任何星星时的效果:

I have been able to achieve the following, which is functional as you can see, but when I look at my code, I feel like there must be a smarter way to do it, and the really bugging part is that IconButton hit area is being shifted up a little bit,so when you touch the actual star it does not register as a touch event (i.e: you have to aim higher than where the button is positioned in order for your touch to be registered, which makes for a bad UX) you can check what I mean by keeping an eye on the splash effect when I click on any of the stars:

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,),
              ],

          ),
        ),
      ),
    );
  }

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

So is what is the better approach here?

推荐答案

重复和填充过多!

无论如何,我就是这么做的。简单,可重用。
您可以在有和没有点击的情况下使用它(没有点击会禁用波纹效果)。
也有半颗星。如果未指定颜色,则对填充的星星使用原色。

Anyway, that's how I'd do it. Simple, reusable. You can use it both with and without clicks (no click disable the ripple effect). Half stars too. And use primary color for filled stars if no color is specified.

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)));
  }
}

然后可以像这样使用它:

You can then use it like this :

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

这篇关于如何正确创建评分星条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆