首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何正确创建收视率星条?

如何正确创建收视率星条?
EN

Stack Overflow用户
提问于 2017-10-09 09:06:56
回答 4查看 23.9K关注 0票数 16

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

我已经实现了以下功能,正如你所看到的,这是功能性的,但当我查看我的代码时,我觉得肯定有一种更聪明的方法来做到这一点,真正令人困扰的是,IconButton的命中区域被向上移动了一点,所以当你触摸实际的星星时,它不会注册为触摸事件(即:你必须瞄准比按钮所在位置更高的位置,才能注册你的触摸,这会造成糟糕的UX)你可以通过关注我点击任何星星时的闪屏效果来检查我的意思:

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

          ),
        ),
      ),
    );
  }

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-10-09 19:49:33

太多的重复和填充!废话

不管怎样,这就是我要做的。简单,可重用。你可以在不点击和不点击的情况下使用(不点击,禁用涟漪效果)。半星也是。如果未指定颜色,则对填充的星形使用原色。

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

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

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),
    );
  }
}
票数 47
EN

Stack Overflow用户

发布于 2017-10-09 16:40:50

发生这种情况的原因是为行小部件指定的高度。手势仅被检测到该高度。删除高度将缩放行以适合子项,从而允许完美地检测IconButton上的点击手势。

我想我做了一个稍微好一点的解决方案。

评分组件代码:

int _rating = 0;

void rate(int rating) {
  //Other actions based on rating such as api calls.
  setState(() {
    _rating = rating;
  });
}

@override
Widget build(BuildContext context) {
  return new Scaffold(
    appBar: new AppBar(
      title: new Text("My Rating"),
    ),
    body: new Center(
      child: new Container(
        width: 500.0,
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new GestureDetector(
              child: new Icon(
                Icons.star,
                color: _rating >= 1 ? Colors.orange : Colors.grey,
              ),
              onTap: () => rate(1),
            ),
            new GestureDetector(
              child: new Icon(
                Icons.star,
                color: _rating >= 2 ? Colors.orange : Colors.grey,
              ),
              onTap: () => rate(2),
            ),
            new GestureDetector(
              child: new Icon(
                Icons.star,
                color: _rating >= 3 ? Colors.orange : Colors.grey,
              ),
              onTap: () => rate(3),
            ),
            new GestureDetector(
              child: new Icon(
                Icons.star,
                color: _rating >= 4 ? Colors.orange : Colors.grey,
              ),
              onTap: () => rate(4),
            ),
            new GestureDetector(
              child: new Icon(
                Icons.star,
                color: _rating >= 5 ? Colors.orange : Colors.grey,
              ),
              onTap: () => rate(5),
            )
          ],
        ),
      ),
    ),
  );
}

如果您希望使用问题中的代码,请替换:

child: new Container(
      height: 10.0,
      width: 500.0,
      child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,

通过以下方式:

child: new Container(
      width: 500.0,
      child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,

希望这能有所帮助!

票数 3
EN

Stack Overflow用户

发布于 2019-03-11 19:11:55

如果任何人也想显示文本,那么您可以使用这段代码。这段代码既可以处理双精度值,也可以处理整型值,我在这里的smoothStarRating中使用了SmoothStarRating小部件。这是相当好的:)如果发现有用,请对此答案给予支持。

Text(
    rate == 5.0
        ? 'Its 5'
        : ((rate < 5.0) & (rate > 3.0))
            ? 'Its 4'
            : ((rate < 4.0) & (rate > 2.0))
                ? 'Its 3'
                : ((rate < 3.0) & (rate > 1.0))
                    ? 'Its 2'
                    : ((rate < 2.0) & (rate > 0.0))
                        ? 'Its 1'
                        : 'Its0',
),
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46637566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档