I’m working a floating action button with some twists: when you click on the FloatingActionButton(), some InkWell() widgets become visible from a Stack(), where you can click on multiple options. When I inserted it to my application, I experienced something weird:
If I add the unique MyFAB() widget as a “home” option within MaterialApp(), the animation works perfectly and you can click on the small InkWell() widgets without any problems:
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyFAB(),
);
}
}
class MyFAB extends StatefulWidget {
const MyFAB({Key? key}) : super(key: key);
@override
State<MyFAB> createState() => _MyFABState();
}
class _MyFABState extends State<MyFAB> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _toggle() {
if (_animationController.isDismissed) {
_animationController.forward();
} else {
_animationController.reverse();
}
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
_buildOption(Icons.mood, -0.2),
_buildOption(Icons.sentiment_satisfied, 0.27),
_buildOption(Icons.sentiment_dissatisfied, 0.72),
_buildOption(Icons.mood_bad, 1.2),
FloatingActionButton(
heroTag: "MyFAB",
onPressed: _toggle,
shape: const CircleBorder(),
child: AnimatedIcon(
icon: AnimatedIcons.menu_close,
progress: _animation,
),
),
],
);
}
Widget _buildOption(IconData icon, double index) {
final double angle = (index - 1.5) * 0.5 * pi;
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
final double offsetX = _animation.value * 70 * cos(angle);
final double offsetY = _animation.value * 70 * sin(angle);
return Transform.translate(
offset: Offset(offsetX, offsetY),
child: Transform.scale(
scale: _animation.value,
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
print('Option tapped');
_toggle();
},
borderRadius: BorderRadius.circular(20),
splashColor: Colors.grey.withOpacity(0.5),
child: CircleAvatar(
radius: 20,
child: Icon(icon),
),
),
),
),
);
},
);
}
}
But if I add MyFAB() into a Scaffold() as a “floatingActionButton”, the small icons become useless, you cannot click on them anymore.
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: MyFAB(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
),
);
}
}
class MyFAB extends StatefulWidget {
const MyFAB({Key? key}) : super(key: key);
@override
State<MyFAB> createState() => _MyFABState();
}
class _MyFABState extends State<MyFAB> with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
_animation = CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOut,
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _toggle() {
if (_animationController.isDismissed) {
_animationController.forward();
} else {
_animationController.reverse();
}
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
_buildOption(Icons.mood, -0.2),
_buildOption(Icons.sentiment_satisfied, 0.27),
_buildOption(Icons.sentiment_dissatisfied, 0.72),
_buildOption(Icons.mood_bad, 1.2),
FloatingActionButton(
heroTag: "MyFAB",
onPressed: _toggle,
shape: const CircleBorder(),
child: AnimatedIcon(
icon: AnimatedIcons.menu_close,
progress: _animation,
),
),
],
);
}
Widget _buildOption(IconData icon, double index) {
final double angle = (index - 1.5) * 0.5 * pi;
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
final double offsetX = _animation.value * 70 * cos(angle);
final double offsetY = _animation.value * 70 * sin(angle);
return Transform.translate(
offset: Offset(offsetX, offsetY),
child: Transform.scale(
scale: _animation.value,
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
print('Option tapped');
_toggle();
},
borderRadius: BorderRadius.circular(20),
splashColor: Colors.grey.withOpacity(0.5),
child: CircleAvatar(
radius: 20,
child: Icon(icon),
),
),
),
),
);
},
);
}
}
I’m a self-taught Flutter developer, still pretty new to it, so I got stuck at this point. What causing this behavior? How can I use MyFAB() within the Scaffold() without any problems?
You can try out my codes in https://dartpad.dev/
Thanks in advance!
I recoded the entire MyFAB() not to use Stack() widget, removed the "floatingActionButtonLocation"
option from the Scaffold(), nothing helped.
avemmortis is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.