如何在 Flutter 的 ShellRoute 中使用 SlideTransition(或其他动画)?

问题描述 投票:0回答:1

我在

ShellRoute
13.0.0 和
go_router
中使用
BottomNavigationBar
来实现嵌套路由。 但是,我注意到屏幕路由时过渡动画不自然。 所以我尝试改变
ShellRoute
中的路由动画,但我不能。 我还找到了与我遇到类似问题的人。

github问题

这是我的代码。

routes.dart

import 'package:baro_project/screens/calendar_screen.dart';
import 'package:baro_project/screens/info_screen.dart';
import 'package:baro_project/screens/youtube_screen.dart';
import 'package:baro_project/widgets/nav_bar.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'screens/login_screen.dart';
import 'screens/main_screen.dart';
import 'screens/noti_screen.dart';

final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'Root');
final GlobalKey<NavigatorState> _shellNavigatorKey = GlobalKey<NavigatorState>(debugLabel: 'Shell');

final router = GoRouter(navigatorKey: _rootNavigatorKey, initialLocation: '/login', routes: <RouteBase>[
  GoRoute(
    path: '/login',
    builder: (context, state) => const Login(),
  ),
  GoRoute(
    path: '/notification',
    builder: (context, state) => const NotificationManager(),
  ),
  ShellRoute(
    navigatorKey: _shellNavigatorKey,
    builder: (context, state, child) => NavBarWidget(child: child),
    routes: <RouteBase>[
      GoRoute(
        path: '/main',
        builder: (context, state) => const MainScreen(),
      ),
      GoRoute(
        path: '/calendar',
        builder: (context, state) => const CalendarScreen(),
      ),
      GoRoute(
        path: '/youtube',
        builder: (context, state) => const YoutubeScreen(),
      ),
      GoRoute(
        path: '/information',
        builder: (context, state) => const InformationScreen(),
      ),
    ],
  ),
]);

nav_bar.dart

import 'package:baro_project/widgets/app_bar.dart';
import 'package:baro_project/widgets/custom_drawer.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart';

class NavBarWidget extends StatelessWidget {
  const NavBarWidget({super.key, required this.child});
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: customAppBar(context),
      body: child,
      bottomNavigationBar: BottomNavigationBar(
        unselectedItemColor: Colors.grey,
        selectedItemColor: Colors.black,
        type: BottomNavigationBarType.fixed,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: FaIcon(FontAwesomeIcons.house, size: 15.0),
            label: 'Main',
          ),
          BottomNavigationBarItem(
            icon: FaIcon(FontAwesomeIcons.calendar, size: 15.0),
            label: 'Calendar',
          ),
          BottomNavigationBarItem(
            icon: FaIcon(FontAwesomeIcons.youtube, size: 15.0),
            label: 'Youtube',
          ),
          BottomNavigationBarItem(
            icon: FaIcon(FontAwesomeIcons.user, size: 15.0),
            label: 'Information',
          ),
        ],
        onTap: (index) => _onItemTapped(index, context),
        currentIndex: _calculateIndex(context),
      ),
      endDrawer: customDrawer(context),
    );
  }

  void _onItemTapped(int index, BuildContext context) {
    switch (index) {
      case 0:
        GoRouter.of(context).go('/main');
        break;
      case 1:
        GoRouter.of(context).go('/calendar');
        break;
      case 2:
        GoRouter.of(context).go('/youtube');
        break;
      case 3:
        GoRouter.of(context).go('/information');
        break;
    }
  }

  int _calculateIndex(BuildContext context) {
    final currentLocation = GoRouterState.of(context).uri.toString();
    if (currentLocation == '/main') {
      return 0;
    }
    if (currentLocation == '/calendar') {
      return 1;
    }
    if (currentLocation == '/youtube') {
      return 2;
    }
    if (currentLocation == '/information') {
      return 3;
    }
    return 0;
  }
}

我试过这个方法。

ShellRoute(
    navigatorKey: _shellNavigatorKey,
    builder: (context, state, child)  {
      var animation = ModalRoute.of(context)?.animation;
      if(animation == null) {
        return NavBarWidget(child: child);
      }
      return SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(0, 1),
          end: Offset.zero,
        ).animate(animation),
        child: NavBarWidget(child: child),
      );
    },

BottomNavigationBar
中,我希望当我单击当前项目时显示向右移动的动画,当我单击左侧项目时显示向左移动的动画。

代码没有出现错误,但是动画没有改变。

my application

此外,iOS模拟器和Android模拟器的基本路由动画的表现方式也有所不同。 我用的是Android模拟器。

我该怎么办?

android ios flutter animation flutter-go-router
1个回答
0
投票

您应该使用 pageBuilder 方法而不是构建器本身,以便能够在路线中使用任何转换。例如:

 ShellRoute(
  pageBuilder: (BuildContext context, GoRouterState state, Widget child) {
    return CustomTransitionPage<void>(
      key: state.pageKey,
      child: ChooseOshiLayoutPage(child: child),
      transitionDuration: const Duration(milliseconds: 250),
      reverseTransitionDuration: const Duration(milliseconds: 250),
      transitionsBuilder: (context, animation, secondaryAnimation, child) =>
          SlideUpPageAnimation(
              context: context,
              animation: animation,
              secondaryAnimation: secondaryAnimation,
              child: child),
    );
  },
  routes: [
    GoRoute(
      name: AppRoutes.chooseOshi,
      path: '/choose-oshi',
      pageBuilder: (context, state) {
        return CustomTransitionPage<void>(
          key: state.pageKey,
          child: const ChooseOshiPage(),
          transitionDuration: const Duration(milliseconds: 250),
          reverseTransitionDuration: const Duration(milliseconds: 250),
          transitionsBuilder: (context, animation, secondaryAnimation,
                  child) =>
              SlideUpPageAnimation(
                  context: context,
                  animation: animation,
                  secondaryAnimation: secondaryAnimation,
                  child: child),
        );
      },
    ),
  ])
© www.soinside.com 2019 - 2024. All rights reserved.