Flutter 封装一个打星的东西
star Widget组件
如果我们封装一个组件的话很明显我们的这个因该足够灵活
所以我们需要给它传很多的参数 其中只有分数是必填参数
- rating: 分数 (必填参数)
- maxRating: 满分
- count: 准备有几颗星
- star: 的大小
- unselectedColor: 未选中的颜色
- unselectedColor: 选中的颜色
- unselectedImage: 自定义为选中的图片
- selectedImage: 自定义选中的图片
这样它就会足够的灵活
同时也为了让他可以打出几点几个星的效果 我们需要做个 图片裁剪的功能
排布设置
我们的星星是水平排布的 所以我们用Row来排布
同时这个Row 的children数组太长我们专门用一个方法来产生数组 这样嵌套的层级少就好看
产生星星 我们使用List.generate 这个函数来动态的产生
import "package:flutter/material.dart";
// 这里是用less还是ful呢 如果有状态的话就用fulWidget
class HYStarRating extends StatefulWidget {
final double rating; //分数是
final double maxRating; //满分是
final int count; //准备有几颗星
final double size; //star的大小
final Color unselectedColor; // 未选中时候的颜色
final Color unselectedColor; // 选中的时候的颜色
final Widget unselectedImage;
final Widget selectedImage;
HYStarRating({
@required this.rating,
this.maxRating = 10,
this.count = 5,
this.size = 30,
this.unselectedColor = const Color(0xffbbbbbb),
this.selectedColor = const Color(0xffff0000),
Widget unselectedImage,
Widget selectedImage
}): unselectedImage = unselectedImage ?? Icon(Icons.star_border, color: unselectedColor, size: size),
selectedImage = selectedImage ?? Icon(Icons.star, color: selectedColor, size: size);
@override
_HYStarRatingState createState() => _HYStarRatingState();
}
class _HYStarRatingState extends State<HYStarRating> {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Row(mainAxisSize: MainAxisSize.min, children: buildUnSelectedStar()),
// 100 70 都因该别人个性化的时候用的
Row(mainAxisSize: MainAxisSize.min, children: buildSelectedStar()),
],
);
}
List<Widget> buildUnSelectedStar() {
return List.generate(widget.count, (index) {
return widget.unselectedImage;
});
}
List<Widget> buildSelectedStar() {
// 1. 创建stars
List<Widget> stars= [];
final star = widget.selectedImage;
// 2. 构建填充的stars
double oneValue = widget.maxRating / widget.count;
// 向下取整 floor ceil
int entireCount = (widget.rating / oneValue).floor();
print(entireCount);
for(var i = 0 ; i < entireCount; i++ ) {
stars.add(star);
}
// 3. 构建部分填充的
// 裁剪Widget
double leftWidth = ((widget.rating / oneValue) - entireCount) * widget.size;
final partStar = ClipRect(
child: star,
clipper: HYStarClipper(leftWidth),
);
stars.add(partStar);
return stars;
}
}
// 我们直接自定义一个类 这个类继承字 CustomClipper这个类是管裁剪的
// 这样就可以打出 半个星 或者几点几个星的效果
class HYStarClipper extends CustomClipper<Rect> {
double width;
HYStarClipper(this.width);
@override
Rect getClip(Size size) {
// TODO: implement getClip
// size.height 垂直方向不裁剪
return Rect.fromLTRB(0, 0, width, size.height);
}
@override
bool shouldReclip(HYStarClipper oldClipper) {
// TODO: implement shouldReclip
// 要不要重新裁剪 宽度不一致的时候
return oldClipper.width != this.width;
}
}
这样就可以使用了
import "package:flutter/material.dart";
import "package:learn_flutter02/douban/widgets/star_rating.dart";
class HYHomeContent extends StatefulWidget {
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
@override
Widget build(BuildContext context) {
return Center(
child: HYStarRating(rating: 2)
);
}
}
换一个 rating: 3