Как сбросить таймер, когда приложение переходит в фоновый режим?

Я пытаюсь сбросить таймер обратного отсчета, когда приложение переходит в фоновый режим. В настоящее время я могу обнаруживать различные состояния жизненного цикла приложения, но не могу понять, как вызвать сброс таймера при обнаружении состояния «пауза».

Детектор жизненного цикла приложения находится в корневом виджете, а «дом» моего корневого виджета в настоящее время является страницей таймера обратного отсчета. (Я настроил его таким образом, чтобы определение жизненного цикла приложения работало во всем приложении, но я не уверен, что это была правильная реализация.)

Сначала я думал, что могу просто сделатьcontroller.resetподcase AppLifecycleState.paused, но я верю, так какcontrollerопределяется позже в моем коде, я не могу использовать его в корневом виджете.

Итак, вот виджет Root:

      class TimerApp extends StatefulWidget {
  const TimerApp({super.key});

  @override
  State<TimerApp> createState() => _TimerAppState();
}

class _TimerAppState extends State<TimerApp> with WidgetsBindingObserver {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.amber,
      ),
      home: const TimerPage(),
    );
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    switch (state) {
     ** case AppLifecycleState.paused:
        debugPrint('Paused State');**
        break;
      case AppLifecycleState.resumed:
        debugPrint('Resumed State');
        break;
      case AppLifecycleState.inactive:
        debugPrint('Incactive State');
        break;
      case AppLifecycleState.detached:
        debugPrint('Detached State');
        break;
    }
  }
}

А вот и виджет страницы таймера обратного отсчета:

      class TimerPage extends StatefulWidget {
  const TimerPage({super.key});

  

  @override
  State<TimerPage> createState() => _TimerPageState();
}

class _TimerPageState extends State<TimerPage> with TickerProviderStateMixin {
  late AnimationController controller;

  bool isPlaying = false;
  

  String get countText {
    Duration count = controller.duration! * controller.value;
    return controller.isDismissed
        ? '${controller.duration!.inHours}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
        : '${count.inHours}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
  }

  double progress = 1.0;
  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 90),
    );
    controller.addListener(
      () {
        if (controller.isAnimating) {
          setState(
            () {
              progress = controller.value;
            },
          );
        } else {
          setState(
            () {
              progress = 1.0;
              isPlaying = false;
            },
          );
        }
      },
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            onPressed: () {
              debugPrint('invert colors');
            },
            icon: const Icon(Icons.invert_colors),
          ),
        ],
      ),
      body: Container(
        color: const Color.fromARGB(255, 152, 57, 57),
        height: 800,
        child: Column(
          children: [
            Expanded(
              child: Center(
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    SizedBox(
                      width: 300,
                      height: 300,
                      child: CircularProgressIndicator(
                        backgroundColor: Colors.grey,
                        value: progress,
                        strokeWidth: 8,
                      ),
                    ),
                    GestureDetector(
                      onTap: () {
                        if (controller.isDismissed) {
                          showModalBottomSheet(
                            context: context,
                            builder: (context) => SizedBox(
                              height: 300,
                              child: CupertinoTimerPicker(
                                initialTimerDuration: controller.duration!,
                                onTimerDurationChanged: (time) {
                                  setState(
                                    () {
                                      controller.duration = time;
                                    },
                                  );
                                },
                              ),
                            ),
                          );
                        }
                      },
                      child: AnimatedBuilder(
                        animation: controller,
                        builder: (context, child) => Text(
                          countText,
                          style: const TextStyle(
                              fontSize: 60, fontWeight: FontWeight.bold),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
              child:
                  Row(mainAxisAlignment: MainAxisAlignment.center, children: [
                GestureDetector(
                  onTap: () {
                    if (controller.isAnimating) {
                      controller.stop();
                      setState(() {
                        isPlaying = false;
                      });
                    } else {
                      controller.reverse(
                          from: controller.value == 0 ? 1.0 : controller.value);
                      setState(
                        () {
                          isPlaying = true;
                        },
                      );
                    }
                  },
                  child: RoundButton(
                      icon: isPlaying == true
                          ? Icons.pause_circle_outline_sharp
                          : Icons.play_circle_outline_sharp),
                ),
                GestureDetector(
                    onTap: () {
                      controller.reset();
                      setState(
                        () {
                          isPlaying = false;
                        },
                      );
                    },
                    child: const RoundButton(icon: Icons.stop_circle_outlined)),
              ]),
            ),
          ],
        ),
      ),
    );
  }
}

Как я могу вызвать сброс таймера при обнаружении состояния паузы?

0 ответов

Другие вопросы по тегам