Files
Test-apk/lib/main.dart

157 lines
4.4 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final notifications = FlutterLocalNotificationsPlugin();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const settings = InitializationSettings(android: androidSettings);
await notifications.initialize(settings);
await notifications.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestNotificationsPermission();
runApp(const TimerApp());
}
class TimerApp extends StatelessWidget {
const TimerApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.light,
)),
home: const TimerScreen(),
);
}
class TimerScreen extends StatefulWidget {
const TimerScreen({super.key});
@override
State<TimerScreen> createState() => _TimerScreenState();
}
class _TimerScreenState extends State<TimerScreen> {
int duration = 60;
int remaining = 60;
Timer? timer;
bool isRunning = false;
void _showNotification() async {
const androidDetails = AndroidNotificationDetails(
'timer_channel',
'Таймер',
channelDescription: 'Уведомления таймера',
importance: Importance.high,
priority: Priority.high,
);
const details = NotificationDetails(android: androidDetails);
await notifications.show(0, 'Таймер завершён!', 'Время вышло.', details);
}
void _startTimer() {
setState(() => isRunning = true);
timer = Timer.periodic(const Duration(seconds: 1), (_) {
if (remaining > 0) {
setState(() => remaining--);
} else {
timer?.cancel();
_showNotification();
setState(() => isRunning = false);
}
});
}
void _pauseTimer() {
timer?.cancel();
setState(() => isRunning = false);
}
void _resetTimer() {
timer?.cancel();
setState(() {
isRunning = false;
remaining = duration;
});
}
void _selectDuration() {
showModalBottomSheet(
context: context,
builder: (_) => Column(
mainAxisSize: MainAxisSize.min,
children: [1, 5, 10, 15, 30, 60].map((m) {
return ListTile(
title: Text('$m мин'),
onTap: () {
setState(() {
duration = m * 60;
remaining = duration;
});
Navigator.pop(context);
},
);
}).toList(),
),
);
}
@override
void dispose() {
timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final minutes = (remaining / 60).floor();
final seconds = remaining % 60;
final progress = duration > 0 ? (remaining / duration) as double : 0.0;
return Scaffold(
appBar: AppBar(title: const Text('Таймер')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: _selectDuration,
child: Stack(
alignment: Alignment.center,
children: [
SizedBox(
width: 200,
height: 200,
child: CircularProgressIndicator(
value: progress,
strokeWidth: 8,
),
),
Text(
'${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}',
style: Theme.of(context).textTheme.displayMedium,
),
],
),
),
const SizedBox(height: 40),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
onPressed: isRunning ? _pauseTimer : _startTimer,
child: Icon(isRunning ? Icons.pause : Icons.play_arrow),
),
if (remaining != duration) ...[
const SizedBox(width: 16),
OutlinedButton(onPressed: _resetTimer, child: const Text('Сброс')),
],
],
),
],
),
);
}
}