首页 > 解决方案 > 如何在flutter中实现这样的过渡效果?

问题描述

我尝试了 Hero 小部件和页面路由来在像这个gif这样的页面之间切换 。

我曾尝试使用自定义页面路由,使用 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)),
    ]);
  }
}

有没有其他思路可以提供?</p>

标签: flutterhero

解决方案


尝试动画,容器变换:

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

推荐阅读