我正在尝试为用户评分创建一个星形栏,以下图片来自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)
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)
演示
另一个很好的选择是使用这个库: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)
| 归档时间: |
|
| 查看次数: |
5314 次 |
| 最近记录: |