Reputation: 497
I am trying to implement this particular dribbble design in Flutter. Any hints on how to proceed?
Upvotes: 0
Views: 1445
Reputation: 2117
As @pskink Suggested, I have tried Flow
widget. Let me know If anyone have better idea.
FlowMenu Statefulwidget
class FlowMenu extends StatefulWidget {
@override
_FlowMenuState createState() => _FlowMenuState();
}
class _FlowMenuState extends State<FlowMenu>
with SingleTickerProviderStateMixin {
AnimationController menuAnimation;
IconData lastTapped = Icons.notifications;
void _updateMenu(IconData icon) {
if (icon != Icons.menu) setState(() => lastTapped = icon);
}
@override
void initState() {
super.initState();
menuAnimation = AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
menuAnimation.addListener(() {
setState(() {});
});
}
Widget flowMenuItem(MenuData menuData) {
return Row(
children: <Widget>[
RawMaterialButton(
fillColor:
lastTapped == menuData.iconData ? Colors.amber[700] : Colors.blue,
splashColor: Colors.amber[100],
shape: CircleBorder(),
onPressed: () {
_updateMenu(menuData.iconData);
menuAnimation.status == AnimationStatus.completed
? menuAnimation.reverse()
: menuAnimation.forward();
},
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Icon(
menuData.iconData,
color: Colors.white,
size: 45.0,
),
),
),
Transform.scale(
scale: menuAnimation.value,
child: Opacity(
opacity: menuAnimation.value,
child: Text(menuData.text),
),
),
],
);
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Flow(
delegate: FlowMenuDelegate(menuAnimation: menuAnimation),
children: menuItems
.map<Widget>((MenuData menuData) => flowMenuItem(menuData))
.toList(),
),
),
],
);
}
}
FlowMenuDelegate - for repaint childrens(menu)
class FlowMenuDelegate extends FlowDelegate {
FlowMenuDelegate({this.menuAnimation}) : super(repaint: menuAnimation);
final Animation<double> menuAnimation;
@override
bool shouldRepaint(FlowMenuDelegate oldDelegate) {
return menuAnimation != oldDelegate.menuAnimation;
}
@override
void paintChildren(FlowPaintingContext context) {
double dx = 0.0, dy = 0.0;
for (int i = 0; i < context.childCount; ++i) {
// dx = context.getChildSize(i).width * i;
dx = 200.0 * cos(menuItems[i].angle * (pi / 180));
dy = 200.0 * sin(menuItems[i].angle * (pi / 180));
context.paintChild(
i,
transform: Matrix4.translationValues(
dx * menuAnimation.value,
dy * menuAnimation.value,
0,
),
);
}
}
}
Test Data
final List<MenuData> menuItems = <MenuData>[
MenuData(iconData: Icons.home, text: "Home", angle: -60),
MenuData(iconData: Icons.new_releases, text: "Release", angle: -30),
MenuData(iconData: Icons.notifications, text: "Notification", angle: 0),
MenuData(iconData: Icons.settings, text: "Settings", angle: 30),
MenuData(iconData: Icons.menu, text: "Menu", angle: 60),
];
Upvotes: 1