0
votes

In my simple part of mobile application i used Hero without any problem and that works fine, now when i try to add a class as Widget which named AnimatedFab in part of this class i get this error:

There are multiple heroes that share the same tag within a subtree.

i don't use any Hero in this class and i'm wondering why i get the error

i used Hero in Stack and implementation code is:

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)),
    )),

and in parent of Stack which above code is one child of that, i have this code:

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

full Stack children:

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)),
            )),
  ],
);

UPDATED

i consider heroTag as a value into below class:

AnimatedFab class which i have problem with that is below code:


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

how can i solve this issue? i think main problem is in _buildFabCore(),, method which i have this in this class.

thanks in advance

1

1 Answers

0
votes

Consider passing a value to heroTag for the FloatingActionButton inside _buildFabCore or simply pass null.
This may happen if you have another FloatingActionButton is used within the app so if you didn't pass different heroTag for each one of them you will get this error.