Как добиться такого эффекта перехода во флаттере?

Я попробовал виджет Hero и маршрут страницы для переключения между страницами, подобными этой гифке.

Я пробовал использовать настраиваемый маршрут страницы, использовать виджет Stack для переноса двух страниц и анимировать в buildTransitions, но сложно рассчитать выравнивание масштаба, и виджет героя не удален с предыдущей страницы.

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

Есть ли еще какие-нибудь идеи??

1 ответ

попробуйте анимацию, преобразование контейнера:

                _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,
    );
  }
}
Другие вопросы по тегам