简体   繁体   English

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

[英]Animated FloatingActionButton in Stack don't trigger onPressed event

I've created an animated Floating Action Button (FAB) menu: Main FAB which spawns other FABs when clicked. 我创建了一个动画浮动操作按钮(FAB)菜单:主FAB在单击时生成其他FAB。 It is based on several online tutorials. 它基于几个在线教程。

Works fine besides one major issue: The spawned FABs don't trigger an onPressed event. 除了一个主要问题之外还可以正常工作:生成的FAB不会触发onPressed事件。

Seems like there's a problem with the combination of transform animation and the stack widget (which the FABs are children of). 似乎变换动画和堆栈小部件(FAB是其子代)的组合存在问题。 Works fine if I replace the stack with a row... 如果我用一行替换堆栈,工作正常......

Seems like the issue was addressed here, but without a proper solution: FloatingActionButton onPressed not triggering 似乎这里解决了这个问题,但没有一个合适的解决方案: FloatingActionButton onPressed没有触发

Here's the complete code for that FAB menu. 这是FAB菜单的完整代码。 Just supply it a list with buttons data, similar to this one: 只需提供一个包含按钮数据的列表,类似于这个:

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)

The code: 编码:

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

}

That's because you are moving the items outside your Stack so you can't hitTest on those positions. 那是因为你正在移动Stack外的items所以你不能在这些位置上hitTest

I modified a few lines of your code to make it works : 我修改了几行代码以使其工作:

  • Add constraints to your Stack (you can use SizedBox also) , I'm using container to set a different color of background. 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))), ); }); } 
  • Center your items 居中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']), ), ); } 

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

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