如何正确创建评分星形条?
我试图创建的用户评级的明星吧,下图是从Play商店来说明什么,我想实现:如何正确创建评分星形条?
我已经能够实现以下,这是功能正如你所看到的,但是当我看着我的代码,我觉得必须有一个更聪明的方式来做到这一点,真正的问题在于IconButton
命中区域正在向上移动一点点,所以当你触摸它没有注册为触摸事件的实际明星(即:你必须瞄准的位置高于按钮定位的位置,以便你的触摸被注册,这会导致用户体验不佳),您可以通过保留注视飞溅效果T当我点击的星星:
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,),
],
),
),
),
);
}
那么,什么是更好的方法吗?
太多的重复和填充!嗯
无论如何,这就是我该怎么做。简单,可重复使用。 无论是否点击都可以使用它(不点击禁用连锁效果)。 也是半星。如果没有指定颜色,则使用原色填充星星。
“黑” 星彩是在这张照片不正确。它在手机上是灰色的,但由于颤动问题,它在我的模拟器中显示为黑色。
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)));
}
}
然后,您可以使用它像这样:
发生这种情况的原因是为行窗口小部件指定了高度。手势只能检测到该高度。删除高度将缩放该行以适合儿童,从而允许完美地检测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,
希望这有助于!
与> =检查的颜色干得漂亮;) –
如何内联率()方法中的onTap:()=>的setState (()=> _rating = 1)? –
如果没有基于评级触发的动作,内联率方法是一个好主意。我认为内联评级可能会导致5次修改,以便根据评级触发任何行动。在费率方法中添加了评论,希望这是有道理的。 –
我不知道我应该设置'onRatingChanged:',为了通过点击启用评级? – aziza
大多数时候,一个''(rating)=> setState(()=> this。评分=评分))'应该够了 – Darky
你能澄清一下吗?不是'onRatingChanged'应该设置为类似于'onRatingChanged:(RatingChangeCallback)=> ....' – aziza