Flutter--页面跳转动画

这个路由提供页面从上下左右自由弹出的动画 ,其他不同形式的动画如法炮制。

import 'package:flutter/material.dart';



class PanPageRouteBuilder extends PageRoute {

  final WidgetBuilder builder;
  final AxisDirection popDirection;

  PanPageRouteBuilder({
    RouteSettings? settings,
    required this.builder,
    this.popDirection = AxisDirection.up,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.reverseTransitionDuration = const Duration(milliseconds: 300),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
    bool fullscreenDialog = false,
  }) : assert(builder != null),
        assert(opaque != null),
        assert(barrierDismissible != null),
        assert(maintainState != null),
        assert(fullscreenDialog != null),
        super(settings: settings, fullscreenDialog: fullscreenDialog);




  @override
  final Duration transitionDuration;

  @override
  final Duration reverseTransitionDuration;

  @override
  final bool opaque;

  @override
  final bool barrierDismissible;

  @override
  final Color? barrierColor;

  @override
  final String? barrierLabel;

  @override
  final bool maintainState;

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

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {

    AxisDirection direction = isActive ? AxisDirection.up : AxisDirection.down; //上入下出

    switch(popDirection) {
      case AxisDirection.up :
        direction = isActive ? AxisDirection.up : AxisDirection.down;
        break;
      case AxisDirection.down :
        direction = isActive ? AxisDirection.down : AxisDirection.up;
        break;
      case AxisDirection.left :
        direction = isActive ? AxisDirection.left : AxisDirection.right;
        break;
      case AxisDirection.right :
        direction = isActive ? AxisDirection.right : AxisDirection.left;
        break;
    }

    return PanTransition(
      child: builder(context),
      direction: direction,
      position: animation,
    );
  }
}

class PanTransition extends AnimatedWidget {
  PanTransition({
    Key? key,
    required Animation<double> position,
    this.transformHitTests = true,
    this.direction = AxisDirection.down,
    required this.child,
  }) : super(key: key, listenable: position) {
    switch (direction) {
      case AxisDirection.up:
        _tween = Tween(begin: const Offset(0, 1), end: const Offset(0, 0));
        break;
      case AxisDirection.right:
        _tween = Tween(begin: const Offset(-1, 0), end: const Offset(0, 0));
        break;
      case AxisDirection.down:
        _tween = Tween(begin: const Offset(0, -1), end: const Offset(0, 0));
        break;
      case AxisDirection.left:
        _tween = Tween(begin: const Offset(1, 0), end: const Offset(0, 0));
        break;
    }
  }

  final bool transformHitTests;

  final Widget child;

  final AxisDirection direction;

  late final Tween<Offset> _tween;

  @override
  Widget build(BuildContext context) {
    final position = listenable as Animation<double>;
    Offset offset = _tween.evaluate(position);
    if (position.status == AnimationStatus.reverse) {
      switch (direction) {
        case AxisDirection.up:
          offset = Offset(offset.dx, -offset.dy);
          break;
        case AxisDirection.right:
          offset = Offset(-offset.dx, offset.dy);
          break;
        case AxisDirection.down:
          offset = Offset(offset.dx, -offset.dy);
          break;
        case AxisDirection.left:
          offset = Offset(-offset.dx, offset.dy);
          break;
      }
    }

    return FractionalTranslation(
      translation: offset,
      transformHitTests: transformHitTests,
      child: child,
    );
  }
}

使用

class RouteTestPage extends StatelessWidget {
  const RouteTestPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: TextButton(onPressed: () {
        Navigator.push(context, PanPageRouteBuilder(builder: (context) => const TargetPage(), popDirection: AxisDirection.up));
      }, child: const Text("PUSH"),),),
      backgroundColor: Colors.green,
    );
  }
}


class TargetPage extends StatelessWidget {

  const TargetPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: TextButton(
        onPressed: () {
          Navigator.of(context).pop();
        },
        child: const Text("POP", style: TextStyle(color: Colors.white),),
      ),),
      backgroundColor: Colors.blueAccent,
    );
  }
}

猜你喜欢

转载自blog.csdn.net/weixin_41735943/article/details/123151766