Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dart 如何正确创建评级星形条?_Dart_Flutter - Fatal编程技术网

Dart 如何正确创建评级星形条?

Dart 如何正确创建评级星形条?,dart,flutter,Dart,Flutter,我正在尝试为用户评级创建一个星形条,下图来自play store,以说明我正在尝试实现的目标: 我已经能够实现以下功能,正如您所看到的,但是当我查看我的代码时,我觉得必须有一种更聪明的方法来实现它,而真正的问题是,IconButton命中区域被上移了一点,所以当您触摸实际的星星时,它不会注册为触摸事件(即:你必须瞄准高于按钮位置的位置,才能注册你的触摸,这会造成糟糕的用户体验)当我点击任何星星时,你可以通过观察飞溅效果来检查我的意思: var\u myColorOne=Colors.grey

我正在尝试为用户评级创建一个星形条,下图来自play store,以说明我正在尝试实现的目标:

我已经能够实现以下功能,正如您所看到的,但是当我查看我的代码时,我觉得必须有一种更聪明的方法来实现它,而真正的问题是,
IconButton
命中区域被上移了一点,所以当您触摸实际的星星时,它不会注册为触摸事件(即:你必须瞄准高于按钮位置的位置,才能注册你的触摸,这会造成糟糕的用户体验)当我点击任何星星时,你可以通过观察飞溅效果来检查我的意思:

var\u myColorOne=Colors.grey;
var _myColorTwo=颜色。灰色;
var_myColorThree=颜色。灰色;
var_myColorFour=颜色。灰色;
var_myColorFive=颜色。灰色;
@凌驾
小部件构建(构建上下文){
归还新脚手架(
appBar:新的appBar(
标题:新文本(“我的评级”),
),
正文:新中心(
子容器:新容器(
身高:10.0,
宽度:500.0,
孩子:新的一排(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
新图标按钮(图标:新图标(Icons.star),
按下时:()=>设置状态(){
_myColorOne=Colors.orange;
_myColorTwo=null;
_myColorThree=null;
_myColorFour=null;
_mycolor5=null;
}),颜色:_myColorOne,),
新图标按钮(图标:新图标(Icons.star),
按下时:()=>设置状态(){
_myColorOne=Colors.orange;
_myColorTwo=颜色。橙色;
_myColorThree=颜色。灰色;
_myColorFour=颜色。灰色;
_myColorFive=颜色。灰色;
}),颜色:_myColorTwo,),
新图标按钮(图标:新图标(Icons.star),ON按下:()=>setState(){
_myColorOne=Colors.orange;
_myColorTwo=颜色。橙色;
_myColorThree=颜色。橙色;
_myColorFour=颜色。灰色;
_myColorFive=颜色。灰色;
}),颜色:_mycolor三,),
新图标按钮(图标:新图标(Icons.star),ON按下:()=>setState(){
_myColorOne=Colors.orange;
_myColorTwo=颜色。橙色;
_myColorThree=颜色。橙色;
_myColorFour=颜色。橙色;
_myColorFive=颜色。灰色;
}),颜色:_myColorFour,),
新图标按钮(图标:新图标(Icons.star),ON按下:()=>setState(){
_myColorOne=Colors.orange;
_myColorTwo=颜色。橙色;
_myColorThree=颜色。橙色;
_myColorFour=颜色。橙色;
_myColorFive=颜色。橙色;
}),颜色:_mycolor5,),
],
),
),
),
);
}

因此,这里更好的方法是什么?

这是因为为行小部件指定了高度。手势仅检测到该高度。移除该高度将缩放行以适合儿童,从而允许完美检测图标按钮上的点击手势

我想我提出了一个稍微好一点的解决方案

评级组件代码:

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


希望这有帮助!

重复和填充太多了!呸

不管怎样,我就是这么做的。简单,可重复使用。 您可以在单击和不单击的情况下使用它(不单击将禁用涟漪效应)。 半星形。如果没有指定颜色,则使用填充星形的原色

typedef void RatingChangeCallback(双重评级);
类星号扩展了无状态小部件{
最终整数星数;
最终双重评级;
最终额定值更改回调额定值更改;
最终颜色;
星号({this.starCount=5,this.rating=0,this.onRatingChanged,this.color});
小部件buildStar(BuildContext上下文,int索引){
图标;
如果(指数>=评级){
图标=新图标(
Icons.star_边框,
颜色:主题。背景。按钮颜色,
);
}
否则如果(指数>评级-1&&指数<评级){
图标=新图标(
图标。星半,
颜色:颜色??主题(上下文)。原色,
);
}否则{
图标=新图标(
明星,
颜色:颜色??主题(上下文)。原色,
);
}
返回新的InkResponse(
onTap:onRatingChanged==null?null:()=>onRatingChanged(索引+1.0),
孩子:图标,
);
}
@凌驾
小部件构建(构建上下文){
返回新行(子项:newlist.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),
    );
  }
}
类测试扩展StatefulWidget{
@凌驾
_TestState createState()=>new_TestState();
}
类_TestState扩展状态{
双重评级=3.5;
@凌驾
小部件构建(构建上下文){
回归新星光(
评级:评级,
onRatingChanged:(评级)=>setState(()=>this.rating=评级),
);
}
}
这是我的

List<bool> ratingStarStatus = <bool>[
true,
false,
false,
false,
false
];

int rating=1;

Widget addImage(String icon){
    return new Image.asset(
        icon,
        height: 25.0,
        width: 25.0,
    );
}

Widget addRatingImage(int index){
    return new InkWell(
        onTap: (){
            rating=index+1;
            reDrawRating(index);
        },
        child: addImage(ratingStarStatus[index]?Constant.iconStarEnable: Constant.iconStarDisable)
    );
}
void reDrawRating(int index){
    for(int i=0;i<5;i++){
        if(i<=index){
            setState(() {
                ratingStarStatus[i]=true;
            });
        }else{
            setState(() {
                ratingStarStatus[i]=false;
        });
        }
    }
}

Widget addRatingView(){
    var stars = <Widget>[];
    for (var i = 0; i < 5; i++) {
        var star = addRatingImage(i);
        var padding = new Padding(padding: const EdgeInsets.fromLTRB(0.0, 0.0, 12.0, 0.0));
        stars.add(star);
        stars.add(padding);
    }

    return new Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: stars,
    );
}
List ratingStarStatus=[
是的,
假,,
假,,
假,,
假的
];
内部评级=1;
小部件添加图像(字符串图标){
返回新的Image.asset(
偶像
身高:25.0,
宽度:25.0,
);
}
小部件添加图像(整数索引){
返回新墨水池(
onTap:(){
评级=指数+1;
重画评级(指数);
},
子项:addImage(评级开始状态[索引]?常量。IConstable:常量。IConstardinable)
);
}
无效重绘(整数索引){

对于(inti=0;i如果有人想显示文本,那么您可以使用这段代码。 该代码既可以用于double,也可以用于in
child: new Container(
      width: 500.0,
      child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,
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),
    );
  }
}
List<bool> ratingStarStatus = <bool>[
true,
false,
false,
false,
false
];

int rating=1;

Widget addImage(String icon){
    return new Image.asset(
        icon,
        height: 25.0,
        width: 25.0,
    );
}

Widget addRatingImage(int index){
    return new InkWell(
        onTap: (){
            rating=index+1;
            reDrawRating(index);
        },
        child: addImage(ratingStarStatus[index]?Constant.iconStarEnable: Constant.iconStarDisable)
    );
}
void reDrawRating(int index){
    for(int i=0;i<5;i++){
        if(i<=index){
            setState(() {
                ratingStarStatus[i]=true;
            });
        }else{
            setState(() {
                ratingStarStatus[i]=false;
        });
        }
    }
}

Widget addRatingView(){
    var stars = <Widget>[];
    for (var i = 0; i < 5; i++) {
        var star = addRatingImage(i);
        var padding = new Padding(padding: const EdgeInsets.fromLTRB(0.0, 0.0, 12.0, 0.0));
        stars.add(star);
        stars.add(padding);
    }

    return new Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: stars,
    );
}
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',
),
`class RatingsWidget extends StatefulWidget {
  @override
  _RatingsWidgetState createState() => _RatingsWidgetState();
}

class _RatingsWidgetState extends State<RatingsWidget> {
  int _rating = 0;

  @override
  Widget build(BuildContext context) {
    List<Widget> array = [];
    var filled = Colors.blue;
    var empty = Colors.black;
    for (var i = 1; i <= 5; i++) {
      array.add(IconButton(
        icon: Icon(Icons.star),
        color: (_rating < i ? empty : filled),
        onPressed: () {
          setState(() {
            _rating = i;
          });
        },
      ));
    }
    return Row(
      children: array,
      mainAxisAlignment: MainAxisAlignment.center,
    );
  }
}`
 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;
        });
      },
      )),
    ),
  );
 }
}
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);
   },
);
class RatingButtons extends StatefulWidget {
  const RatingButtons({
    Key key,
    @required this.feedbackIcons,
  }) : super(key: key);

  final List<Widget> feedbackIcons;
//Here you can create a list of icons for rating or 
//you can pass the icon list while using this widget

  @override
  _RatingButtonsState createState() => _RatingButtonsState();
}

class _RatingButtonsState extends State<RatingButtons> {
  int rating;

  @override
  Widget build(BuildContext context) {
    return Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
      ...widget.feedbackIcons.map((icon) {
        return GestureDetector(
          child: rating == widget.feedbackIcons.indexOf(icon)
              ? CircleAvatar(
                  radius: 30,
                  backgroundColor: kThemeColor,
                  child: icon,
                )
              : icon,
          onTap: () {
            setState(() {
              rating = widget.feedbackIcons.indexOf(icon);
            });
          },
        );
      }).toList()
    ]);
  }
}