Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как реализуешь pop-up?
Pop-up (всплывающее окно) — один из самых часто используемых элементов UI в Flutter. Существует несколько способов его реализации в зависимости от требований и типа pop-up.
Встроенные диалоги Flutter
AlertDialog — самый простой и универсальный вариант:
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Подтверждение\u0027),
content: Text('Вы уверены?\u0027),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Отмена\u0027),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: Text('Да\u0027),
),
],
);
},
);
SimpleDialog для выбора
Когда нужно предоставить пользователю список выборов:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: Text('Выберите опцию\u0027),
children: [
SimpleDialogOption(
onPressed: () => Navigator.pop(context, 'option1\u0027),
child: Text('Опция 1\u0027),
),
SimpleDialogOption(
onPressed: () => Navigator.pop(context, 'option2\u0027),
child: Text('Опция 2\u0027),
),
],
);
},
);
Кастомный диалог
Для более сложных pop-up нужен кастомный виджет:
class CustomPopup extends StatelessWidget {
final String title;
final String message;
final VoidCallback onConfirm;
const CustomPopup({
required this.title,
required this.message,
required this.onConfirm,
});
@override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
SizedBox(height: 16),
Text(message),
SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Отмена\u0027),
),
ElevatedButton(
onPressed: onConfirm,
child: Text('Подтвердить\u0027),
),
],
),
],
),
),
);
}
}
// Использование
showDialog(
context: context,
builder: (context) => CustomPopup(
title: 'Заголовок\u0027,
message: 'Сообщение\u0027,
onConfirm: () => Navigator.pop(context),
),
);
BottomSheet вместо диалога
Для меню снизу используется showModalBottomSheet:
showModalBottomSheet(
context: context,
builder: (context) => Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Text('Опция 1\u0027),
onTap: () => Navigator.pop(context),
),
ListTile(
title: Text('Опция 2\u0027),
onTap: () => Navigator.pop(context),
),
],
),
),
);
Анимированный pop-up
Для красивой анимации используется PopScope и AnimatedBuilder:
class AnimatedPopup extends StatefulWidget {
@override
State<AnimatedPopup> createState() => _AnimatedPopupState();
}
class _AnimatedPopupState extends State<AnimatedPopup> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(duration: Duration(milliseconds: 300), vsync: this);
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ScaleTransition(
scale: _animation,
child: AlertDialog(
title: Text('Анимированный диалог\u0027),
content: Text('С красивой анимацией\u0027),
),
);
}
}
Рекомендации
- AlertDialog — для простых подтверждений
- SimpleDialog — для выбора из списка
- BottomSheet — для меню снизу экрана
- Кастомный Dialog — для сложного UI
- GetX или Provider — для управления состоянием pop-up
Лучшая практика — создать переиспользуемый utility класс для всех диалогов в приложении, чтобы обеспечить консистентность UI и легко менять стиль глобально.