堆栈中的动画FloatingActionButton不会触发onPressed事件

时间:2019-04-03 19:52:23

标签: animation flutter

我创建了一个动画的浮动动作按钮(FAB)菜单: 单击时会生成其他FAB的主FAB。 它基于一些在线教程。

除了一个主要问题之外,还可以正常工作: 产生的FAB不会触发onPressed事件。

似乎转换动画和堆栈小部件(FAB是其子级)的组合存在问题。 如果我用一行替换堆栈,效果很好...

似乎在这里已解决了该问题,但没有适当的解决方案: FloatingActionButton onPressed not triggering

这是该FAB菜单的完整代码。 只需提供一个包含按钮数据的列表,类似于此:

List<Map<String, dynamic>> _buttonsData = [
{'color': Colors.green ,'icon': Icons.stop},
{'color': Colors.blue ,'icon': Icons.subway},
{'color': Colors.green ,'icon': Icons.add},];
FancyFab2(_buttonsData, null)

代码:

import 'package:flutter/material.dart';


class FancyFab extends StatefulWidget {
  FancyFab(this._buttonsData, this._onSelected);

  final List<Map<String, dynamic>> _buttonsData;
  final ValueChanged<int> _onSelected;

  @override
  createState() => FancyFabState(_buttonsData, _onSelected);
}

class FancyFabState extends State<FancyFab> with SingleTickerProviderStateMixin {
  final List<Map<String, dynamic>> _buttonsData;
  final ValueChanged<int> _onSelected;

  // state vars
  AnimationController _controller;
  Animation <double> _transform;

  bool _isOpened = false;

  FancyFabState(this._buttonsData, this._onSelected);

  @override
  void initState() {
    // call base
    super.initState();

    // _controller
    _controller = AnimationController(
      duration: Duration(milliseconds: 100),
      vsync: this
    );

    _transform = Tween<double>(
      begin: 0.0,
      end: -64.0,
    ).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Curves.fastOutSlowIn
      ),
    );
  }

  @override
  void dispose() {
    // controller
    _controller.dispose();

    // call base
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return _buildFab(_controller);
  }

  Widget _buildFab(AnimationController controller) {
    return AnimatedBuilder(
      animation: controller,
      builder: (context, builder) {
        return Stack(
          children: List.generate(_buttonsData.length, (index) => _buildStackWidget(context, index))
        );
      }
    );
  }

  Widget _buildStackWidget(BuildContext context, int index) {
    Map<String, dynamic> buttonData = _buttonsData[index];
    if (index == _buttonsData.length - 1)
      return _buildMenuButton(index, buttonData);
    else
      return _buildMenuItem(index, buttonData);
  }

  Widget _buildMenuItem(int index, Map<String, dynamic> buttonData) {
    return Transform.translate(
      offset: Offset((1 + index) * _transform.value, 0.0),
      child: FloatingActionButton(
        heroTag: 100 + index,
        backgroundColor: buttonData['color'],
        //onPressed: () => _onSelected(index),
        onPressed: () => print('click'),
        child: Icon(buttonData['icon']),
      ),
    );
  }

  Widget _buildMenuButton(int index, Map<String, dynamic> buttonData) {
    return FloatingActionButton(
      heroTag: 200,
      backgroundColor: buttonData['color'],
      onPressed: _toggle,
      child: Icon(buttonData['icon']),
    );
  }

  void _toggle() {
    print('toggle');
    _isOpened = !_isOpened;
    if (true == _isOpened)
      _controller.forward();
    else
      _controller.reverse();
  }

}

1 个答案:

答案 0 :(得分:0)

那是因为您正在将items移到Stack之外,所以无法hitTest在这些位置上。

我修改了几行代码以使其起作用:

  • 向您的Stack添加约束(也可以使用SizedBox),我正在使用容器设置不同的背景颜色。

          Widget _buildFab(AnimationController controller) {
            return AnimatedBuilder(
                animation: controller,
                builder: (context, builder) {
                  return Container(
                    width: MediaQuery.of(context).size.width,
                    height: 100,
                    color: Colors.blueGrey,
                    child: Stack(
                        children: List.generate(_buttonsData.length,
                            (index) => _buildStackWidget(context, index))),
                  );
                });
          }
    
  • items

    居中
        Widget _buildMenuItem(int index, Map<String, dynamic> buttonData) {
            return Center(
              child: Transform.translate(
                offset: Offset((1 + index) * _transform.value, 0.0),
                child: FloatingActionButton(
                  heroTag: 100 + index,
                  backgroundColor: buttonData['color'],
                  //onPressed: () => _onSelected(index),
                  onPressed: () => print('click'),
                  child: Icon(buttonData['icon']),
                ),
              ),
            );
          }
    
          Widget _buildMenuButton(int index, Map<String, dynamic> buttonData) {
            return Center(
              child: FloatingActionButton(
                heroTag: 200,
                backgroundColor: buttonData['color'],
                onPressed: _toggle,
                child: Icon(buttonData['icon']),
              ),
            );
          }