У меня есть флаттер-приложение с итерациями, и на каждой итерации есть кнопка обратного отсчета.
Когда я нажимаю кнопку, обратный отсчет всех итераций работает, однако моя цель - заставить работать только один обратный отсчет.
Вот функция обратного отсчета:
int _countdownTime = 45;
late Timer _countdownTimer = Timer(Duration(seconds: 0), () {});
void startCountdownTimer() {
const oneSec = const Duration(seconds: 1);
_countdownTimer = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_countdownTime < 1) {
timer.cancel();
_countdownTime = 45; // Reset countdown timer to 45 seconds
} else {
_countdownTime = _countdownTime - 1;
}
},
),
);
}
void _handleCountdownTap() {
if (_countdownTimer == null || !_countdownTimer.isActive) {
startCountdownTimer();
}
}
вот интерфейс:
for (var breakdown in snapshot.data![index].breakdowns)
Card(
margin: EdgeInsets.zero,
child: Padding(
padding: EdgeInsets.only(bottom: 8.0, right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Text(
'${breakdown.order}',
textAlign: TextAlign.center,
),
),
SizedBox(
height: 30,
child: GestureDetector(
onTap: _handleCountdownTap,
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: Center(
child: Text(
'$_countdownTime seconds',
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
),
),
),
),
],
),
),
),
Мой вопрос, как заставить работать только один таймер обратного отсчета при нажатии вместо всех итераций в разбивке. Есть ли другое решение или подход для решения этой проблемы
Вы можете создать виджет, который имеет логику таймера для каждого элемента. Что-то вроде
for (var breakdown in snapshot.data![index].breakdowns) {
BreakdownCard(
key: ValueKey(breakdown.order),
label: breakdown.order);
}
class BreakdownCard extends StatefulWidget {
final String label;
const BreakdownCard({super.key, required this.label});
@override
State<BreakdownCard> createState() => _BreakdownCardState();
}
class _BreakdownCardState extends State<BreakdownCard> {
int _countdownTime = 45;
Timer _countdownTimer = Timer(const Duration(seconds: 0), () {});
void startCountdownTimer() {
const oneSec = Duration(seconds: 1);
_countdownTimer = Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_countdownTime < 1) {
timer.cancel();
_countdownTime = 45; // Reset countdown timer to 45 seconds
} else {
_countdownTime = _countdownTime - 1;
}
},
),
);
}
void _handleCountdownTap() {
if (!_countdownTimer.isActive) {
startCountdownTimer();
}
}
@override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.zero,
child: Padding(
padding: const EdgeInsets.only(bottom: 8.0, right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Text(
widget.label,
textAlign: TextAlign.center,
),
),
SizedBox(
height: 30,
child: GestureDetector(
onTap: _handleCountdownTap,
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: Center(
child: Text(
'$_countdownTime seconds',
style: const TextStyle(
fontSize: 15,
color: Colors.white,
),
),
),
),
),
),
],
),
),
);
}
}
Что-то вроде этого?
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: CountdownExample(),
);
}
}
class CountdownExample extends StatefulWidget {
@override
_CountdownExampleState createState() => _CountdownExampleState();
}
class _CountdownExampleState extends State<CountdownExample> {
List<int> _countdownTimes = List.filled(3, 45);
final List<Timer?> _countdownTimers = List.filled(3, null);
void startCountdownTimer(int index) {
const oneSec = const Duration(seconds: 1);
_countdownTimers[index] = new Timer.periodic(
oneSec,
(Timer timer) => setState(
() {
if (_countdownTimes[index] < 1) {
timer.cancel();
_countdownTimes[index] = 45; // Reset countdown timer to 45 seconds
} else {
_countdownTimes[index] = _countdownTimes[index] - 1;
}
},
),
);
}
void _handleCountdownTap(int index) {
if (_countdownTimers[index] == null || !_countdownTimers[index]!.isActive) {
startCountdownTimer(index);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Countdown Example'),
),
body: ListView.builder(
itemCount: 3,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: EdgeInsets.all(8.0),
child: Padding(
padding: EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
flex: 1,
child: Text(
'Breakdown ${index + 1}',
textAlign: TextAlign.center,
),
),
SizedBox(
height: 30,
child: GestureDetector(
onTap: () => _handleCountdownTap(index),
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: Center(
child: Text(
'${_countdownTimes[index]} seconds',
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
),
),
),
),
],
),
),
);
},
),
);
}
}