Flutter Floating Action Menu Inside Listview
Last updated Jul 28, 2021In this Flutter example we will learn how to create floating action menu in flutter. To create floating action menu we are going to use Flow widget with custom menus. We are applying animation while floating the menu items. Here we are adding floating action menu inside listview with multiple items
Flow widget constructor
Flow({
Key? key,
required this.delegate,
List<Widget> children = const <Widget>[],
this.clipBehavior = Clip.hardEdge,
})
|
The delegate property that controls the transformation matrices of the children.
final FlowDelegate delegate
Let's get started
Step 1: Create Flutter application
Step 2: Create Flow Menu items
final List<IconData> menuItems = <IconData>[
Icons.home,
Icons.new_releases,
Icons.notifications,
Icons.settings,
Icons.menu,
];
|
Step 3: Set Menu item widget dimensions and its click events
Widget flowMenuItem(IconData icon,BuildContext context) {
final double buttonDiameter = MediaQuery.of(context).size.width / menuItems.length;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 4),
child: Container(
height: 28,
width: 28,
child: RawMaterialButton(
fillColor: lastTapped == icon ? Colors.amber[700] : Colors.blue,
splashColor: Colors.amber[100],
shape: CircleBorder(),
constraints: BoxConstraints.tight(Size(buttonDiameter, buttonDiameter)),
onPressed: () {
_updateMenu(icon);
menuAnimation.status == AnimationStatus.completed
? menuAnimation.reverse()
: menuAnimation.forward();
},
child: Container(
child: Icon(
icon,
color: Colors.white,
size: 14.0,
),
),
),
),
);
}
|
Step 4: Create Animation Controller to handle the Animation of the widget expand and collapse
menuAnimation = AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
|
Step 5: Now add Child items to Listview
ListView.builder(
itemCount: 5,
itemBuilder: (ctx,index){
return ItemList();
})
|
Step 6: Run Application
![]() |
Complete code
list_item.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
class ItemList extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return ItemListState();
}
}
class ItemListState extends State<ItemList> with SingleTickerProviderStateMixin{
late AnimationController menuAnimation;
IconData lastTapped = Icons.notifications;
final List<IconData> menuItems = <IconData>[
Icons.home,
Icons.new_releases,
Icons.notifications,
Icons.settings,
Icons.menu,
];
List<Color>colors=<Color>[
Colors.green,Colors.blue,Colors.pink,Colors.brown,Colors.red
];
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: 90,
margin: EdgeInsets.only(top: 24,left: 16,right: 8),
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(16),
border: Border.all(width: 2.0, color: Colors.grey),
),
child: Center(
child: ListTile(
leading: CircleAvatar(
radius : 28 ,
backgroundColor: Colors.white ,
child: CircleAvatar(
radius: 26,
backgroundImage: NetworkImage(
"https://i.pinimg.com/originals/71/83/70/7183704aac01413c86805c19c1586e2b.jpg"),
),
),
title: Text(
"Freedom Fighter",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700,color: Colors.deepPurple),
),
subtitle: Text(
'Freedom Fighter',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: Colors.white),
),
trailing: Card(
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
width: 50,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('5',
style: TextStyle(
fontSize: 20, color: Colors.grey)),
SizedBox(
width: 1,
),
Icon(
Icons.access_alarms_outlined,
textDirection: TextDirection.rtl,
size: 20,
color: Colors.grey,
)
],
),
),
),
),
),
),
),
Container(
height: 80,
margin: EdgeInsets.only(left: 16),
child: Flow(
clipBehavior: Clip.antiAliasWithSaveLayer,
delegate: FlowMenuDelegate(menuAnimation: menuAnimation),
children: menuItems.map<Widget>((IconData icon) => flowMenuItem(icon,context)).toList(),
),
)
],
);
}
Widget flowMenuItem(IconData icon,BuildContext context) {
final double buttonDiameter = MediaQuery.of(context).size.width / menuItems.length;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 4),
child: Container(
height: 32,
width: 32,
child: RawMaterialButton(
fillColor: lastTapped == icon ? Colors.amber[700] : colors[Random().nextInt(5)],
splashColor: Colors.amber[100],
shape: CircleBorder(),
constraints: BoxConstraints.tight(Size(buttonDiameter, buttonDiameter)),
onPressed: () {
_updateMenu(icon);
menuAnimation.status == AnimationStatus.completed
? menuAnimation.reverse()
: menuAnimation.forward();
},
child: Container(
child: Icon(
icon,
color: Colors.white,
size: 14.0,
),
),
),
),
);
}
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,
);
}
}
class FlowMenuDelegate extends FlowDelegate {
FlowMenuDelegate({required 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;
for (int i = 0; i < context.childCount; ++i) {
dx = context.getChildSize(i)!.width * i;
context.paintChild(
i,
transform: Matrix4.translationValues(
dx * menuAnimation.value,
0,
0,
),
);
}
}
}
|
Article Contributed By :
|
|
|
|
889 Views |