How to achieve transition effect like this in flutter?

596 Views Asked by At

I tried Hero widget and page route to switch between pages like this gif.

I had try with custom page route, use Stack widget to wrap two pages, and animated in buildTransitions, but it is hard to calculate scale alignment and hero widget didn't remove from the previous page.

class CustomPageRoute extends MaterialPageRoute {
  final Widget parentWidget;
  final Alignment parentAlignment;
  final Tween<double> childScaleTween;
  final double childWidth;

  CustomPageRoute(
      {required this.parentWidget,
      required this.parentAlignment,
      required this.childScaleTween,
      required this.childWidth,
      required WidgetBuilder builder,
      RouteSettings? settings})
      : super(builder: builder, settings: settings);

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return builder(context);
  }

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    Curve animatedCurves = Curves.linear;
    var scale = MediaQuery.of(context).size.width / childWidth;
    var scaleAnim = Tween(begin: 1.0, end: scale)
        .animate(CurvedAnimation(parent: animation, curve: animatedCurves));
    var fadeAnim = Tween(begin: 1.0, end: 0.0)
        .animate(CurvedAnimation(parent: animation, curve: animatedCurves));
    var childScaleAnim = childScaleTween
        .animate(CurvedAnimation(parent: animation, curve: animatedCurves));
    var childFadeAnim = Tween(begin: 0.0, end: 1.0)
        .animate(CurvedAnimation(parent: animation, curve: animatedCurves));

    return Stack(children: [
      Container(
        color: Colors.white,
      ),
      ScaleTransition(
          scale: scaleAnim,
          alignment: parentAlignment,
          child: FadeTransition(opacity: fadeAnim, child: parentWidget)),
      ScaleTransition(
          scale: childScaleAnim,
          alignment: parentAlignment,
          child: FadeTransition(opacity: childFadeAnim, child: child)),
    ]);
  }
}

Are there any other ideas to provide?

1

There are 1 best solutions below

0
On

try animations, Container transform:

          _OpenContainerWrapper(
            transitionType: _transitionType,
            closedBuilder: (BuildContext _, VoidCallback openContainer) {
              return _ExampleCard(openContainer: openContainer);
            },
            onClosed: _showMarkedAsDoneSnackbar,
          ),

class _OpenContainerWrapper extends StatelessWidget {
  const _OpenContainerWrapper({
    required this.closedBuilder,
    required this.transitionType,
    required this.onClosed,
  });

  final CloseContainerBuilder closedBuilder;
  final ContainerTransitionType transitionType;
  final ClosedCallback<bool?> onClosed;

  @override
  Widget build(BuildContext context) {
    return OpenContainer<bool>(
      transitionType: transitionType,
      openBuilder: (BuildContext context, VoidCallback _) {
        return const _DetailsPage();
      },
      onClosed: onClosed,
      tappable: false,
      closedBuilder: closedBuilder,
    );
  }
}