![请添加图片描述](https://img-blog.csdnimg.cn/f3ce321f3200406eb0d3febab39f17f1.jpeg)
九宫格抽奖
class SimpleLotteryValue {
SimpleLotteryValue(
{this.target = 0, this.isFinish = false, this.isPlaying = false});
int target = 0;
bool isPlaying = false;
bool isFinish = false;
SimpleLotteryValue copyWith({
int target = 0,
bool isPlaying = false,
bool isFinish = false,
}) {
return SimpleLotteryValue(
target: target, isFinish: isFinish, isPlaying: isPlaying);
}
@override
String toString() {
return "target : $target , isPlaying : $isPlaying , isFinish : $isFinish";
}
}
class SimpleLotteryController extends ValueNotifier {
SimpleLotteryController() : super(SimpleLotteryValue());
void start(int target) {
assert(target >= 0 && target <= 8);
if (value.isPlaying) {
return;
}
value = value.copyWith(target: target, isPlaying: true);
}
void finish() {
value = value.copyWith(isFinish: true);
}
}
class SimpleLotteryWidget extends StatefulWidget {
final Function()? onPress;
final SimpleLotteryController simpleLotteryController;
final List commodityList;
const SimpleLotteryWidget({
Key? key,
required this.commodityList,
required this.onPress,
required this.simpleLotteryController
}) : super(key: key);
@override
State<SimpleLotteryWidget> createState() => _SimpleLotteryWidgetState();
}
class _SimpleLotteryWidgetState extends State<SimpleLotteryWidget> with TickerProviderStateMixin,AutomaticKeepAliveClientMixin{
Future<int>? future;
@override
Widget build(BuildContext context) {
super.build(context);
return FutureBuilder(
future: future,
builder: (context, snapshot) {
return SizedBox(
width: 250,
height: 250,
child: GridView.builder(
physics: const BouncingScrollPhysics(),
itemCount: 9,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, crossAxisSpacing: 6, mainAxisSpacing: 6),
itemBuilder: (context, index) {
if (index != 4) {
return commodity(index);
}
return GestureDetector(
onTap: widget.onPress,
child: lotteryButton,
);
}
)
);
},
);
}
Widget get lotteryButton{
return GestureDetector(
onTap: widget.onPress,
child: const DecoratedBox(
decoration: BoxDecoration(
color: Colors.deepOrangeAccent,
borderRadius: BorderRadius.all(Radius.circular(15))
),
child:Center(
child: Text(
"点击\n抽奖",
style: TextStyle(
fontSize: 15,
color: Colors.white,
fontWeight: FontWeight.bold,
height: 1.2
),
),
),
),
);
}
Widget commodity(int index){
final int toIndex;
if(index > 4){
toIndex = _deserializeMap[index];
}else{
toIndex = _deserializeMap[index];
}
final dataInfo = widget.commodityList[toIndex];
return Stack(
children: [
Container(
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(15)),
image: DecorationImage(
image:CachedNetworkImageProvider(
dataInfo["prize_img"],
scale: 0.5,
),
fit: BoxFit.cover
)
),
),
Container(decoration: BoxDecoration(
color: index == _currentSelect
? Colors.yellow.withOpacity(0.5)
: Colors.transparent,
borderRadius: const BorderRadius.all(Radius.circular(15)),
)),
],
);
}
Animation? _selectedIndexTween;
AnimationController? _startAnimateController;
int _currentSelect = -1;
int _target = 0;
final int repeatRound = 3;
VoidCallback? _listener;
final Map _selectMap = {
0: 0,
1: 3,
2: 6,
3: 7,
4: 8,
5: 5,
6: 2,
7: 1
};
final Map _deserializeMap = {
0: 0,
3: 1,
6: 2,
7: 3,
8: 4,
5: 5,
2: 6,
1: 7
};
simpleLotteryWidgetState() {
_listener = () {
if (widget.simpleLotteryController.value.isPlaying) {
_startAnimateController?.reset();
_target = widget.simpleLotteryController.value.target;
_selectedIndexTween = _initSelectIndexTween(_target);
_startAnimateController?.forward();
}
};
}
Animation _initSelectIndexTween(int target) =>
StepTween(begin: 0, end: repeatRound * 8 + target).animate(
CurvedAnimation(
parent: _startAnimateController!, curve: Curves.easeOutQuart));
@override
void initState() {
super.initState();
future = Future.value(42);
_startAnimateController =
AnimationController(vsync: this, duration: const Duration(seconds: 5));
_selectedIndexTween = _initSelectIndexTween(_target);
simpleLotteryWidgetState();
widget.simpleLotteryController.addListener(_listener!);
_startAnimateController?.addListener(() {
_currentSelect = _selectMap[_selectedIndexTween?.value % 8];
if (_startAnimateController!.isCompleted) {
widget.simpleLotteryController.finish();
}
setState(() {});
});
}
@override
void deactivate() {
widget.simpleLotteryController.removeListener(_listener!);
super.deactivate();
}
@override
void dispose() {
_startAnimateController?.dispose();
widget.simpleLotteryController.dispose();
super.dispose();
}
@override
bool get wantKeepAlive => true;
}
外部调用
final SimpleLotteryController _simpleLotteryController = SimpleLotteryController();
_simpleLotteryController.start(5)
Center(
child: SimpleLotteryWidget(
commodityList: dataList,
onPress: () {
_simpleLotteryController.start(5);
},
simpleLotteryController: _simpleLotteryController,
),
)