flutter 九宫格抽奖

请添加图片描述

九宫格抽奖
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());

  /// 开启抽奖
  ///
  /// [target] 中奖目标
  void start(int target) {
    // 九宫格抽奖里范围为0~8
    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
              )
          ),
          // child: Text(toIndex.toString()),
        ),
        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();
      }
    };
  }

  /// 初始化tween
  ///
  /// [target] 中奖的目标
  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
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

外部调用
final SimpleLotteryController _simpleLotteryController = SimpleLotteryController();
 _simpleLotteryController.start(5) //开启
Center(
            child: SimpleLotteryWidget(
              commodityList: dataList,
              onPress: () {
                _simpleLotteryController.start(5);
                // _simpleLotteryController.start(Random().nextInt(8));
              },
              simpleLotteryController: _simpleLotteryController,
            ),
)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值