繁体   English   中英

Flutter 转换 animation 打破底部导航栏中浮动操作按钮的“按下” function。 需要解决方法

[英]Flutter transform animation breaks “on pressed” function of floating action button in bottom nav bar. Workaround needed

我目前正在尝试实现单击底部导航菜单中的浮动操作按钮时出现的径向菜单(image1)。 animation 和渲染工作正常,但在 animation 之后,按下按钮 function 甚至没有触发,当按钮被点击时。 我已经读到这是由于堆栈、包装按钮和 animation。 转换按钮的区域不是先验定义的。 这会导致按钮的手势检测停留在 FAB 之后。 用固定大小的容器包装 Stack 解决了这个问题,但是,它完全破坏了布局。 此外,由于容器位于导航栏上方,因此无法访问背景中的可点击导航图标(参见图 2)。 是否有解决此问题的已知解决方法? 我真的很期待得到一些专业的帮助。 :)

不工作的按钮和所需布局的图像

使用容器包装堆栈后损坏的 UI 的图像。 但是在这个解决方案中,按下的按钮正在工作

代码附在这里:

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();
      }
    }

我现在无法测试,但包装在容器中似乎是正确的解决方法,因为转换似乎不适用于无边界框中的命中测试行为(这就是 Container 使其工作的原因)。 也许有一种方法(某种小部件或属性)允许像 GestureDetector 这样的 hitTestBehavior,您可以将其设置为“不透明区域”,而不是 Container 的整个边界框捕获触摸。 抱歉,我无法直接为您提供答案,稍后将在计算机上查看:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM