Flutter разрешает несколько героев, которые используют один и тот же тег в поддереве

#flutter

#flutter

Вопрос:

В моей простой части мобильного приложения я использовал Hero без каких-либо проблем, и это работает нормально, теперь, когда я пытаюсь добавить класс, Widget который назван AnimatedFab в части этого класса, я получаю эту ошибку:

Существует несколько героев, которые используют один и тот же тег в поддереве.

я не использую их Hero в этом классе, и мне интересно, почему я получаю ошибку

я использовал Hero в Stack и код реализации:

 Positioned(
    top: 259.0,
    left: 6.0,
    child:  SizedBox(
      key: _imageKey,
      width: 43.0,
      height: 43.0,
      child: InkWell(onTap: () {
        //...
      },child: MyHero(hiveFeed: widget.hiveFeeds)),
    )),
  

и в родительском Stack коде которого приведенный выше код является одним из дочерних элементов, у меня есть этот код:

 Positioned(top: 140.0, right: -40.0, child: const AnimatedFab().pl(8.0)),
  

полные Stack дочерние элементы:

 return Stack(
    children: [
        Card(
          child: Stack(
            children: [
              Positioned(top: 140.0, right: -40.0, child: const AnimatedFab().pl(8.0)),
            ],
          ),
        ),
        Positioned(
            top: 259.0,
            left: 6.0,
            child:  SizedBox(
              key: _imageKey,
              width: 43.0,
              height: 43.0,
              child: InkWell(onTap: () {
                //...
              },child: MyHero(hiveFeed: widget.hiveFeeds)),
            )),
  ],
);
  

ОБНОВЛЕНО

я рассматриваю heroTag как значение в классе ниже:

AnimatedFab класс, с которым у меня проблема, находится ниже кода:

 
Positioned(top: 140.0, right: -40.0, child: AnimatedFab(key:_imageKey).pl(8.0)),


class AnimatedFab extends StatefulWidget {
  final VoidCallback onPressed;
  final Key _key;
  const AnimatedFab({Key key, this.onPressed}) : _key = key;

  @override
  _AnimatedFabState createState() => _AnimatedFabState();
}

class _AnimatedFabState extends State<AnimatedFab> with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<Color> _colorAnimation;

  final double expandedSize = 160.0;
  final double hiddenSize = 50.0;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
    _colorAnimation = ColorTween(begin: Colors.transparent, end: Colors.pink[800]).animate(_animationController);
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: expandedSize,
      height: expandedSize,
      child: AnimatedBuilder(
        animation: _animationController,
        builder: (BuildContext context, Widget child) {
          return Stack(
            alignment: Alignment.center,
            children: <Widget>[
              _buildFabCore(widget.key),
            ],
          );
        },
      ),
    );
  }

  Widget _buildOption(IconData icon, double angle) {
    if (_animationController.isDismissed) {
      return Container();
    }
    double iconSize = 0.0;
    if (_animationController.value > 0.8) {
      iconSize = 26.0 * (_animationController.value - 0.8) * 5;
    }
    return Transform.rotate(
      angle: angle,
      child: Align(
        alignment: Alignment.topCenter,
        child: Padding(
          padding: const EdgeInsets.only(top: 8.0),
          child: IconButton(
            onPressed: _onIconClick,
            icon: Transform.rotate(
              angle: -angle,
              child: Icon(
                icon,
                color: Colors.black54,
              ),
            ),
            iconSize: iconSize,
            alignment: Alignment.center,
            padding: const EdgeInsets.all(0.0),
          ),
        ),
      ),
    );
  }

  Widget _buildExpandedBackground() {
    final double size = hiddenSize   (expandedSize - hiddenSize) * _animationController.value;
    return AnimatedOpacity(
      opacity: _animationController.value,
      duration: const Duration(milliseconds: 300),
      child: Card(
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(100.0)),
        elevation: 4.0,
        child: Container(
          height: size,
          width: size,
        ),
      ),
    );
  }

  Widget _buildFabCore(Key key) {
    final double scaleFactor = 2 * (_animationController.value - 0.5).abs();
    return FloatingActionButton(
      key: key,
      elevation: 0.0,
      mini: true,
      onPressed: _onFabTap,
      backgroundColor: _colorAnimation.value,
      child:  Transform(
        alignment: Alignment.center,
        transform:  Matrix4.identity()..scale(1.0, scaleFactor),
        child:  Icon(
          _animationController.value > 0.5 ? Icons.close : Icons.filter_list,
          color: _animationController.value > 0.5 ? Colors.white:Colors.black54,
          size: 26.0,
        ),
      ),
    );
  }

  void open() {
    if (_animationController.isDismissed) {
      _animationController.forward();
    }
  }

  void close() {
    if (_animationController.isCompleted) {
      _animationController.reverse();
    }
  }

  void _onFabTap() {
    if (_animationController.isDismissed) {
      open();
    } else {
      close();
    }
  }

  void _onIconClick() {
    widget.onPressed();
    close();
  }
}
  

как я могу решить эту проблему? я думаю, что основная проблема заключается в _buildFabCore(), методе, который у меня есть в этом классе.

заранее спасибо

Ответ №1:

Рассмотрите возможность передачи значения heroTag для FloatingActionButton внутри _buildFabCore или просто передать null .
Это может произойти, если у вас есть другой FloatingActionButton , который используется в приложении, поэтому, если вы не передали разные heroTag для каждого из них, вы получите эту ошибку.

Комментарии:

1. FloatingActionButton не имеет никакого Hero тега и считает null, например, key: null, не разрешает проблему. и передача ключа в этот метод тоже не решает проблему, пожалуйста, просмотрите мой пост

2. @DolDurma пожалуйста, проверьте еще раз. FloatingActionButton имеет heroTag в качестве параметра. просто передайте его как elevation и mini .