Create an Animated Radial Menu in Flutter
In this tutorial, we will create an animated radial menu in Flutter using the provided code. The radial menu will consist of several options arranged in a circular pattern, and when the user taps on the menu button, the options will animate into view.
Let's get started!
Folder Structure
To keep our project organized, let's create a folder structure as follows:
- lib - screens - radial_menu_screen.dart - controllers - radial_menu_controller.dart - main.dart
Implementation
First, let's create the `radial_menu_controller.dart` file inside the `controllers` folder. This controller class will handle the opening and closing of the radial menu.
import 'package:flutter/material.dart';
class RadialMenuController {
late ValueChanged<bool> onStateChanged;
bool _opened = false;
bool get opened => _opened;
void open() {
_opened = true;
onStateChanged(true);
}
void close() {
_opened = false;
onStateChanged(false);
}
}
Finally, let's update the `main.dart` file to include the `RadialMenuScreen` as the home screen of our app.
import 'package:flutter/material.dart';
import '../controllers/radial_menu_controller.dart';
class RadialMenuScreen extends StatefulWidget {
const RadialMenuScreen({Key? key}) : super(key: key);
@override
_RadialMenuScreenState createState() => _RadialMenuScreenState();
}
class _RadialMenuScreenState extends State<RadialMenuScreen> {
late RadialMenuController controller;
@override
void initState() {
super.initState();
controller = RadialMenuController();
controller.onStateChanged = (bool opened) {
setState(() {});
};
}
Widget _buildOption(Icon icon, Color iconColor) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
transitionBuilder: (Widget child, Animation<double> animation) {
return RotationTransition(turns: animation, child: child);
},
child: InkWell(
key: UniqueKey(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 50.0,
width: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: iconColor,
),
child: Center(child: icon),
),
),
onTap: () {},
),
);
}
@override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
body: Stack(
children: <Widget>[
// App Bar
Positioned(
top: 0,
left: 0,
right: 0,
child: AppBar(
backgroundColor: Colors.orange,
centerTitle: true,
leading: InkWell(
onTap: () {
Navigator.pop(context);
},
child: const Icon(
Icons.chevron_left,
size: 22,
),
),
elevation: 0,
title: const Text('Radial Menu'),
),
),
// Menu Options
AnimatedPositioned(
duration: const Duration(milliseconds: 300),
left: controller.opened
? MediaQuery.of(context).size.width / 2 - 40.0
: MediaQuery.of(context).size.width / 2 - 150.0,
top: (MediaQuery.of(context).size.height / 2) - 30,
child: _buildOption(
const Icon(Icons.mail_outline, color: Colors.white),
Colors.purple,
),
),
// Add more AnimatedPositioned widgets for other menu options
// Menu Button
Align(
alignment: Alignment.center,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
transitionBuilder: (Widget child, Animation<double> animation) {
return ScaleTransition(scale: animation, child: child);
},
child: controller.opened
? InkWell(
key: UniqueKey(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40.0),
color: Colors.orange,
),
child: const Center(
child: Icon(Icons.share, color: Colors.white),
),
),
),
onTap: () {
controller.close();
},
)
: InkWell(
key: UniqueKey(),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40.0),
color: Colors.red,
),
child: const Center(
child: Icon(Icons.close, color: Colors.white),
),
),
),
onTap: () {
controller.open();
},
),
),
),
],
),
),
);
}
}
That's it! You have successfully created an animated radial menu in Flutter. Run the app to see the menu in action.
Feel free to customize the menu options and the appearance to fit your needs.
Happy coding!
Comments
Post a Comment