Skip to content

Instantly share code, notes, and snippets.

@diegoveloper
Last active October 28, 2023 20:21
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save diegoveloper/1cd23e79a31d0c18a67424f0cbdfd7ad to your computer and use it in GitHub Desktop.
Save diegoveloper/1cd23e79a31d0c18a67424f0cbdfd7ad to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
class FadeIndexedStack extends StatefulWidget {
final int index;
final List<Widget> children;
final Duration duration;
const FadeIndexedStack({
Key key,
this.index,
this.children,
this.duration = const Duration(
milliseconds: 800,
),
}) : super(key: key);
@override
_FadeIndexedStackState createState() => _FadeIndexedStackState();
}
class _FadeIndexedStackState extends State<FadeIndexedStack>
with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void didUpdateWidget(FadeIndexedStack oldWidget) {
if (widget.index != oldWidget.index) {
_controller.forward(from: 0.0);
}
super.didUpdateWidget(oldWidget);
}
@override
void initState() {
_controller = AnimationController(vsync: this, duration: widget.duration);
_controller.forward();
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _controller,
child: IndexedStack(
index: widget.index,
children: widget.children,
),
);
}
}
@aliak00
Copy link

aliak00 commented Oct 15, 2020

This fades the selected stack index widget in, but doesn't fade the one that is going out, out. Is there a way to get that working?

@hetkpatel
Copy link

This solution works really well

@Maruf-S
Copy link

Maruf-S commented Dec 17, 2020

Thankyou sir, i now will be stealing this😁

@kurtsk
Copy link

kurtsk commented Dec 23, 2020

🤘

@XavierSoh
Copy link

Works fine . Thank you.

@jagomf
Copy link

jagomf commented Apr 20, 2021

Hey @diegoveloper, regarding null safety:

  • line 9: key should be nullable: Key? key
  • lines 10 and 11: both named arguments are required
  • line 23: I'd declare AnimationController _controller as late to avoid Dart warning not_initialized_non_nullable_instance_field.

@lucasfalcaoo
Copy link

Great, man! Really great!

@sumeetkumar1
Copy link

sumeetkumar1 commented Sep 24, 2021

Extremely Help full thank you. I will be modifying it for my needs

@MinhCuongIT
Copy link

Thanks a lot!

@Eng-MFQ
Copy link

Eng-MFQ commented Dec 31, 2021

Thanks bro it very useful and smart

@bakhbk
Copy link

bakhbk commented Jul 19, 2022

Thanks a lot!

@Stafferson
Copy link

Thank a lot!
I have a question about changing that white flash during the transition
is there any way to change it?

@Stafferson
Copy link

Ive found the solution. All you need is to change the theme colors of the app

@Ahmadre
Copy link

Ahmadre commented Nov 19, 2022

Here's an improved version with supporting all apis needed:

import 'package:flutter/material.dart';

class FadeIndexedStack extends StatefulWidget {
  final int index;
  final List<Widget> children;
  final Duration duration;
  final AlignmentGeometry alignment;
  final TextDirection? textDirection;
  final Clip clipBehavior;
  final StackFit sizing;

  const FadeIndexedStack({
    super.key,
    required this.index,
    required this.children,
    this.duration = const Duration(
      milliseconds: 250,
    ),
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.clipBehavior = Clip.hardEdge,
    this.sizing = StackFit.loose,
  });

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

class FadeIndexedStackState extends State<FadeIndexedStack>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller =
      AnimationController(vsync: this, duration: widget.duration);

  @override
  void didUpdateWidget(FadeIndexedStack oldWidget) {
    if (widget.index != oldWidget.index) {
      _controller.forward(from: 0.0);
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void initState() {
    _controller.forward();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return FadeTransition(
      opacity: _controller,
      child: IndexedStack(
        index: widget.index,
        alignment: widget.alignment,
        textDirection: widget.textDirection,
        clipBehavior: widget.clipBehavior,
        sizing: widget.sizing,
        children: widget.children,
      ),
    );
  }
}

@mrobinson108
Copy link

Thanks for the code. Nicely done.

@Ali-Kheiri
Copy link

Thank you very much
very useful

@lucasshiva
Copy link

This was very useful, thank you. I made some changes to support lazy loading and published it as a package, to make it easier to use. The package is called fade_indexed_stack.

@mrRedSun
Copy link

class FadeIndexedStack extends StatefulWidget {
  final int index;
  final List<Widget> children;
  final Duration duration;

  const FadeIndexedStack({
    required this.index,
    required this.children,
    this.duration = const Duration(
      milliseconds: 100,
    ),
    super.key,
  });

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

class _FadeIndexedStackState extends State<FadeIndexedStack> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void didUpdateWidget(FadeIndexedStack oldWidget) {
    if (!mounted) return super.didUpdateWidget(oldWidget);

    if (widget.index != oldWidget.index) {
      _controller.forward(from: 0.0);
    }

    super.didUpdateWidget(oldWidget);
  }

  @override
  void initState() {
    _controller = AnimationController(vsync: this, duration: widget.duration);
    _controller.forward();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return FadeTransition(
      opacity: _controller,
      // required for errors not to occur during rapid switching between tabs
      child: RepaintBoundary(
        child: IndexedStack(
          index: widget.index,
          children: widget.children,
        ),
      ),
    );
  }
}

If rapid switching is not working well for you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment