Как сбросить таймер, когда приложение переходит в фоновый режим?
Я пытаюсь сбросить таймер обратного отсчета, когда приложение переходит в фоновый режим. В настоящее время я могу обнаруживать различные состояния жизненного цикла приложения, но не могу понять, как вызвать сброс таймера при обнаружении состояния «пауза».
Детектор жизненного цикла приложения находится в корневом виджете, а «дом» моего корневого виджета в настоящее время является страницей таймера обратного отсчета. (Я настроил его таким образом, чтобы определение жизненного цикла приложения работало во всем приложении, но я не уверен, что это была правильная реализация.)
Сначала я думал, что могу просто сделать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)),
]),
),
],
),
),
);
}
}
Как я могу вызвать сброс таймера при обнаружении состояния паузы?