Пакет star_menu для Flutter: создание красивых контекстных меню
FlutterPulseЭта статья переведена специально для канала FlutterPulse. В этом канале вы найдёте много интересных вещей, связанных с Flutter. Не забывайте подписываться! 🚀

Любой виджет может быть элементом.
Раота с разными формами
Линейная форма
Линейная форма является самой простой. Элементы выстраиваются в прямую линию:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.linear,
linearShapeParams: LinearShapeParams(
angle: 90, // вертикальная линия
space: 10, // расстояние между элементами
alignment: LinearAlignment.center,
),
),
items: menuItems,
child: yourTriggerWidget,
)
Вы можете изменить angle чтобы сделать линию горизонтальной, диагональной или любой другой направленности. Параметр space контролирует расстояние между элементами.

Круглая форма
Круглая форма выглядит наиболее впечатляюще. Элементы располагаются в идеальном круге вокруг триггера:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.circle,
circleShapeParams: CircleShapeParams(
radiusX: 120,
radiusY: 120,
startAngle: 0,
endAngle: 360,
),
),
items: menuItems,
child: yourTriggerWidget,
)
Вы можете создавать овальные формы, используя разные значения radiusX и radiusY. StartAngle и endAngle позволяют создавать частичные круги.

Сеточная форма
Сеточная форма работает лучше всего для многих элементов меню:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.grid,
gridShapeParams: GridShapeParams(
columns: 3,
columnsSpaceH: 15,
columnsSpaceV: 15,
),
),
items: menuItems,
child: yourTriggerWidget,
)
Это создает сетку с 3 столбцами и расстоянием 15 пикселей. Идеально подходит для запуска приложений или палитры инструментов.

Добавление анимаций
Анимации делают меню более живыми. Вы можете контролировать несколько аспектов анимации:
StarMenuParameters(
openDurationMs: 600,
closeDurationMs: 200,
rotateItemsAnimationAngle: 45,
startItemScaleAnimation: 0.1,
animationCurve: Curves.bounceOut,
)
Элементы могут вращаться при появлении. Они могут начинаться с малого размера и увеличиваться до полного размера. Разные кривые создают разные ощущения.

Обработка взаимодействий пользователя
Вы хотите знать, когда пользователь нажимает на элементы меню:
StarMenu(
params: StarMenuParameters(),
items: menuItems,
onItemTapped: (index, controller) {
print('Пользователь нажал на элемент $index');
// Закрыть меню после выбора
controller.closeMenu();
// Обработать действие
switch (index) {
case 0:
navigateToHome();
break;
case 1:
openSearch();
break;
}
},
child: triggerWidget,
)
Функция обратного вызова дает вам индекс элемента и контроллер. Контроллер позволяет вам программно закрыть меню.
Подменю
Меню Star может быть добавлено к любому виджету. Таким образом, мы можем создать меню с элементами, а затем добавить меню Star к каждому элементу и так далее, в результате чего получится меню с подменю любой глубины.
static List<Widget> buildAnimatedMenuItems() {
return [
_buildCircularItem(Icons.home, Colors.deepPurple),
_buildCircularItem(Icons.search, Colors.deepPurple),
_buildCircularItem(Icons.settings, Colors.deepPurple),
_buildCircularItem(Icons.favorite, Colors.deepPurple).addStarMenu(
items: subMenuEntries(),
params: const StarMenuParameters(
shape: MenuShape.linear,
linearShapeParams: LinearShapeParams(
angle: 120,
space: 15,
),
checkMenuScreenBoundaries: true,
),
),
];
}Обратите внимание, что существует метод расширения, который можно использовать вместо конструктора StarMenu.

Расширенные функции
Ленивая загрузка элементов
Иногда вам нужно создавать элементы меню динамически:
StarMenu(
params: StarMenuParameters(),
lazyItems: () async {
// Симулировать вызов API
await Future.delayed(Duration(milliseconds: 200));
return [
buildDynamicItem('Новый элемент 1'),
buildDynamicItem('Новый элемент 2'),
];
},
child: triggerWidget,
)
Это полезно, когда содержимое меню зависит от данных пользователя или ответов API.

Эффекты фона
Сделайте меню более привлекательным с помощью эффекта размытия фона:
StarMenuParameters(
backgroundParams: BackgroundParams(
animatedBlur: true,
sigmaX: 5.0,
sigmaY: 5.0,
animatedBackgroundColor: true,
backgroundColor: Colors.black.withValues(alpha: 0.3),
),
)
Это создает размытый фон, который плавно появляется.

Полный код на GitHub
Чтобы не перегружать историю кодом, вышеуказанные фрагменты кода содержат только необходимые части кода.
Полный код моего демо находится здесь (GetX).
Официальные примеры пакета находятся здесь.
Счастливого кодинга!
