[英]Flutter transform animation breaks “on pressed” function of floating action button in bottom nav bar. Workaround needed
I'm currently trying to implement a radial menu appearing when the floating action button in the bottom navigation menu is clicked (image1).我目前正在尝试实现单击底部导航菜单中的浮动操作按钮时出现的径向菜单(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. animation 和渲染工作正常,但在 animation 之后,按下按钮 function 甚至没有触发,当按钮被点击时。 I already read that this is due to the stack, wrapping the buttons and the animation.我已经读到这是由于堆栈、包装按钮和 animation。 The area of the transformed buttons is not defined a priori.转换按钮的区域不是先验定义的。 This causes gesture detection of the Buttons to stay behind the FAB.这会导致按钮的手势检测停留在 FAB 之后。 Wrapping the Stack with a fixed size container solves the problem, however, it totally breaks the layout.用固定大小的容器包装 Stack 解决了这个问题,但是,它完全破坏了布局。 Also, the clickable navigations icons in the background are not reachable as the container is laying above the navbar (see image2).此外,由于容器位于导航栏上方,因此无法访问背景中的可点击导航图标(参见图 2)。 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.使用容器包装堆栈后损坏的 UI 的图像。 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).我现在无法测试,但包装在容器中似乎是正确的解决方法,因为转换似乎不适用于无边界框中的命中测试行为(这就是 Container 使其工作的原因)。 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.也许有一种方法(某种小部件或属性)允许像 GestureDetector 这样的 hitTestBehavior,您可以将其设置为“不透明区域”,而不是 Container 的整个边界框捕获触摸。 Sorry cause i cant provide you an answer directly, will check it out later on the computer:)抱歉,我无法直接为您提供答案,稍后将在计算机上查看:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.