簡體   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