我在
ShellRoute
13.0.0 和 go_router
中使用 BottomNavigationBar
来实现嵌套路由。
但是,我注意到屏幕路由时过渡动画不自然。
所以我尝试改变ShellRoute
中的路由动画,但我不能。
我还找到了与我遇到类似问题的人。
这是我的代码。
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
中,我希望当我单击当前项目时显示向右移动的动画,当我单击左侧项目时显示向左移动的动画。
代码没有出现错误,但是动画没有改变。
此外,iOS模拟器和Android模拟器的基本路由动画的表现方式也有所不同。 我用的是Android模拟器。
我该怎么办?
您应该使用 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),
);
},
),
])