如何通过Flutter_Bloc库使用BLOC模式?

发布于 2025-01-21 12:40:13 字数 4122 浏览 3 评论 0原文

我正在使用Flutter编写一个小型Tamagotchi应用程序,现在我正在学习如何使用Flutter_Bloc lib。 当用户点击屏幕上的PET图像时,它必须重新绘制一个圆形的percenticticator小部件,但它行不通。我正在尝试使用BlocBuilder和BlocProvider类将视图与BLOC连接起来,但这无济于事。 敲击PET小部件后,将动画转发,但饱和度和循环摄入剂的状态尚未更新。

这是我用于宠物喂养的集团:

class PetFeedingBloc extends Bloc<SaturationEvent, SaturationState> {
  PetFeedingBloc()
      : super(const SaturationState(saturationCount: 40.0)) {
    on<SaturationSmallIncrementEvent>((event, emit) => state.saturationCount + 15.0);
    on<SaturationBigIncrementEvent>((event, emit) => state.saturationCount + 55.0);
    on<SaturationDecrementEvent>((event, emit) => state.saturationCount - 2.0);
  }
}

在饱和式barwidget类中,我试图将一个带有集团的小部件中的一个百分比指示灯连接起来,但它行不通。这是:

class SaturationBarWidget extends StatefulWidget {
  const SaturationBarWidget({Key? key}) : super(key: key);

  @override
  State<SaturationBarWidget> createState() => SaturationBarWidgetState();
}

class SaturationBarWidgetState extends State<SaturationBarWidget> {
  @override
  void initState() {
    Timer? timer;
    timer = Timer.periodic(const Duration(milliseconds: 3000), (_) {
      setState(() {
        context.read<PetFeedingBloc>().add(SaturationDecrementEvent());
        if (context.read<PetFeedingBloc>().state.saturationCount <= 0) {
          timer?.cancel();
        }
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PetFeedingBloc, SaturationState>(builder: (context, state){
      return CircularPercentIndicator(
        radius: 50.0,
        lineWidth: 20.0,
        animateFromLastPercent: true,
        percent: context.read<PetFeedingBloc>().state.saturationCount / 100,
        center: const Icon(
          Icons.emoji_emotions_outlined,
          size: 50.0,
        ),
        backgroundColor: Colors.blueGrey,
        progressColor: Colors.blue,
      );
    });
  }
}

这是我的petwidget班,带有图像需要挖掘:

class PetWidget extends StatefulWidget {
  const PetWidget({Key? key}) : super(key: key);

  @override
  State<PetWidget> createState() => PetWidgetState();
}

class PetWidgetState extends State<PetWidget> with TickerProviderStateMixin {
  late Animation<Offset> _animation;
  late AnimationController _animationController;
  static GlobalKey<SaturationBarWidgetState> key = GlobalKey();
  bool reverse = true;
  Image cat = Image.asset('images/cat.png');

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 4));
    _animation = Tween<Offset>(begin: Offset.zero, end: const Offset(1, 0))
        .animate(CurvedAnimation(
            parent: _animationController, curve: Curves.elasticIn));
    _animationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _animationController.reverse();
      }
    });
    //_animationController.forward();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(child:
        BlocBuilder<PetFeedingBloc, SaturationState>(builder: (context, state) {
          return Center(
              child: SizedBox(
                width: 300,
                height: 400,
                child: SlideTransition(
                  position: _animation,
                  child: GestureDetector(
                    child: cat,
                    onDoubleTap: () {
                      context.read<PetFeedingBloc>().add(SaturationBigIncrementEvent());
                      _animationController.forward();
                    },
                    onTap: () {
                      context.read<PetFeedingBloc>().add(SaturationSmallIncrementEvent());
                      _animationController.forward();
                    },
                  ),
                ),
              )
          );
        })
    );
  }
}

I'm writting a small tamagotchi app using Flutter and now I'm learning how to use flutter_bloc lib.
When user tap on a pet image on a screen, it must redraw a CircularPercentIndicator widget, but it won't work. I'm trying to connect a view with a bloc using a BlocBuilder and BlocProvider classes, but it did not help.
After tapping a pet widget, animation is forwarded, but the state of saturationCount and CircularPercentIndicator hasn't been updated.

Here is my BLoC for pet feeding:

class PetFeedingBloc extends Bloc<SaturationEvent, SaturationState> {
  PetFeedingBloc()
      : super(const SaturationState(saturationCount: 40.0)) {
    on<SaturationSmallIncrementEvent>((event, emit) => state.saturationCount + 15.0);
    on<SaturationBigIncrementEvent>((event, emit) => state.saturationCount + 55.0);
    on<SaturationDecrementEvent>((event, emit) => state.saturationCount - 2.0);
  }
}

In SaturationBarWidget class I'm trying to connect a percent indicator in a widget with a BLoC, but it does not work. Here it is:

class SaturationBarWidget extends StatefulWidget {
  const SaturationBarWidget({Key? key}) : super(key: key);

  @override
  State<SaturationBarWidget> createState() => SaturationBarWidgetState();
}

class SaturationBarWidgetState extends State<SaturationBarWidget> {
  @override
  void initState() {
    Timer? timer;
    timer = Timer.periodic(const Duration(milliseconds: 3000), (_) {
      setState(() {
        context.read<PetFeedingBloc>().add(SaturationDecrementEvent());
        if (context.read<PetFeedingBloc>().state.saturationCount <= 0) {
          timer?.cancel();
        }
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<PetFeedingBloc, SaturationState>(builder: (context, state){
      return CircularPercentIndicator(
        radius: 50.0,
        lineWidth: 20.0,
        animateFromLastPercent: true,
        percent: context.read<PetFeedingBloc>().state.saturationCount / 100,
        center: const Icon(
          Icons.emoji_emotions_outlined,
          size: 50.0,
        ),
        backgroundColor: Colors.blueGrey,
        progressColor: Colors.blue,
      );
    });
  }
}

And here it is my PetWidget class with image that need to be tapped:

class PetWidget extends StatefulWidget {
  const PetWidget({Key? key}) : super(key: key);

  @override
  State<PetWidget> createState() => PetWidgetState();
}

class PetWidgetState extends State<PetWidget> with TickerProviderStateMixin {
  late Animation<Offset> _animation;
  late AnimationController _animationController;
  static GlobalKey<SaturationBarWidgetState> key = GlobalKey();
  bool reverse = true;
  Image cat = Image.asset('images/cat.png');

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: const Duration(seconds: 4));
    _animation = Tween<Offset>(begin: Offset.zero, end: const Offset(1, 0))
        .animate(CurvedAnimation(
            parent: _animationController, curve: Curves.elasticIn));
    _animationController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        _animationController.reverse();
      }
    });
    //_animationController.forward();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(child:
        BlocBuilder<PetFeedingBloc, SaturationState>(builder: (context, state) {
          return Center(
              child: SizedBox(
                width: 300,
                height: 400,
                child: SlideTransition(
                  position: _animation,
                  child: GestureDetector(
                    child: cat,
                    onDoubleTap: () {
                      context.read<PetFeedingBloc>().add(SaturationBigIncrementEvent());
                      _animationController.forward();
                    },
                    onTap: () {
                      context.read<PetFeedingBloc>().add(SaturationSmallIncrementEvent());
                      _animationController.forward();
                    },
                  ),
                ),
              )
          );
        })
    );
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

人海汹涌 2025-01-28 12:40:13

我认为您必须在您中调用Emit方法
PetFeedingBloc

class PetFeedingBloc extends Bloc<SaturationEvent, SaturationState> {
  PetFeedingBloc()
      : super(const SaturationState(saturationCount: 40.0)) {
    on<SaturationSmallIncrementEvent>((event, emit) => emit(SaturationState(saturationCount: state.saturationCount + 15.0)) );
   ...
  }
}

I think you have to call the emit method in you
PetFeedingBloc

class PetFeedingBloc extends Bloc<SaturationEvent, SaturationState> {
  PetFeedingBloc()
      : super(const SaturationState(saturationCount: 40.0)) {
    on<SaturationSmallIncrementEvent>((event, emit) => emit(SaturationState(saturationCount: state.saturationCount + 15.0)) );
   ...
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文