letsar / local_hero

A widget which implicitly launches a hero animation when its position changed within the same route.
MIT License
208 stars 48 forks source link

fix: should not flicker #21

Open Tienisto opened 2 months ago

Tienisto commented 2 months ago

When the widget is initially not visible, then there is one frame where the animated widget takes the full screen.

Reproduction code:

class FlickeringTestWidget extends StatefulWidget {
  const FlickeringTestWidget({super.key});

  @override
  State<FlickeringTestWidget> createState() => _FlickeringTestWidgetState();
}

class _FlickeringTestWidgetState extends State<FlickeringTestWidget> {
  double topPadding = 0;
  bool visible = false;

  @override
  void initState() {
    super.initState();

    Future.delayed(const Duration(milliseconds: 1000), () {
      setState(() {
        visible = true;
      });
    });

    Future.delayed(const Duration(milliseconds: 2000), () {
      setState(() {
        topPadding = 100;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Opacity(
      opacity: visible ? 1 : 0,
      child: LocalHeroScope(
        child: Align(
          alignment: Alignment.topLeft,
          child: Padding(
            padding: EdgeInsets.only(top: topPadding),
            child: LocalHero(
              tag: 'id',
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
          ),
        ),
      ),
    );
  }
}