I'm currently trying to implement a radial menu appearing when the floating action button in the bottom navigation menu is clicked (image1). The animation and rendering works fine but after the animation, the on pressed button function is no even triggered, when the buttons get clicked. I already read that this is due to the stack, wrapping the buttons and the animation. The area of the transformed buttons is not defined a priori. This causes gesture detection of the Buttons to stay behind the FAB. Wrapping the Stack with a fixed size container solves the problem, however, it totally breaks the layout. Also, the clickable navigations icons in the background are not reachable as the container is laying above the navbar (see image2). Is there a known workaround to fix this problem? I am really looking forward to getting some professional help. :)
Image of not working buttons and desired layout
Image of the broken UI after wrapping the stack with a container. But in this solution button pressed is working
The code is attached here:
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:vector_math/vector_math.dart' show radians;
class RadialFloatingActionButton extends StatefulWidget {
@override
_RadialFloatingActionButtonState createState() => _RadialFloatingActionButtonState();
}
class _RadialFloatingActionButtonState extends State<RadialFloatingActionButton> with
SingleTickerProviderStateMixin {
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(milliseconds: 1100), vsync: this);
}
@override
Widget build(BuildContext context) {
return RadialAnimation(controller: controller);
}
}
class RadialAnimation extends StatelessWidget {
RadialAnimation({Key key, this.controller})
: scale = Tween<double>(
begin: 1.5,
end: 0.0,
).animate(
CurvedAnimation(parent: controller, curve: Curves.elasticInOut),
),
translation = Tween<double>(
begin: 0.0,
end: 90.0,
).animate(
CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc),
),
super(key: key);
final AnimationController controller;
final Animation<double> scale;
final Animation<double> translation;
build(context) {
return AnimatedBuilder(
animation: controller,
builder: (context, builder) {
return Stack(alignment: Alignment.center, children: [
_buildButton(200, color: Colors.black, emoji: "A"),
_buildButton(245, color: Colors.black, emoji: "B"),
_buildButton(295, color: Colors.black, emoji: "C"),
_buildButtonMore(340, color: Colors.grey),
Transform.scale(
scale: scale.value -
1.5, // subtract the beginning value to run the opposite animation
child: FloatingActionButton(
child: Icon(
Icons.close,
),
onPressed: _close,
backgroundColor: Colors.black),
),
Transform.scale(
scale: scale.value,
child: FloatingActionButton(
child: Icon(
Icons.people,
color: Colors.white,
),
onPressed: _open,
backgroundColor: Colors.black),
)
]);
});
}
_buildButtonMore(double angle, {Color color}) {
final double rad = radians(angle);
return Transform(
transform: Matrix4.identity()
..translate(
(translation.value) * cos(rad), (translation.value) * sin(rad)),
child: FloatingActionButton(
child: Icon(Icons.more_horiz),
backgroundColor: color,
onPressed: _close,
elevation: 0));
}
_buildButton(double angle, {Color color, String emoji}) {
final double rad = radians(angle);
return Transform(
transform: Matrix4.identity()
..translate(
(translation.value) * cos(rad), (translation.value) * sin(rad)),
child: FloatingActionButton(
child: Center(
child: new Text(
emoji,
style: TextStyle(fontSize: 30),
textAlign: TextAlign.center,
),
),
backgroundColor: color,
onPressed: _close,
elevation: 0));
}
_open() {
controller.forward();
}
_close() {
controller.reverse();
}
}
I am not able to test right now, but wrapping in a container seems like the proper workaround, as Transforms seems to not apply to hit test behaviors in unbounding boxes (thats why Container makes it work). Maybe there's a way (some sort of widget or property) that allows hitTestBehavior like GestureDetector where you can set it to “opaque areas” instead the entire bounding box of the Container capturing the touches. Sorry cause i cant provide you an answer directly, will check it out later on the computer:)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.