fix: use StatefulShellRoute to fix ui rerendering

This commit is contained in:
Simon Ding
2024-11-04 11:24:27 +08:00
parent c28373bde1
commit bb6da47efb

View File

@@ -49,77 +49,81 @@ class _MyAppState extends ConsumerState<MyApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var padding = isSmallScreen(context) ? 5.0 : 20.0;
// GoRouter configuration // GoRouter configuration
final shellRoute = ShellRoute( final shellRoute = StatefulShellRoute.indexedStack(
builder: (BuildContext context, GoRouterState state, Widget child) { builder: (BuildContext context, GoRouterState state,
StatefulNavigationShell navigationShell) {
return SelectionArea( return SelectionArea(
child: MainSkeleton( child: MainSkeleton(
body: Padding( body: navigationShell,
padding: EdgeInsets.only(
left: padding, right: padding, top: 5, bottom: 5),
child: child),
), ),
); );
}, },
routes: [ branches: [
GoRoute( StatefulShellBranch(routes: [
path: "/", GoRoute(
redirect: (context, state) => WelcomePage.routeTv, path: WelcomePage.routeTv,
), pageBuilder: (context, state) => buildPageWithDefaultTransition(
GoRoute( context: context, state: state, child: const WelcomePage()),
path: WelcomePage.routeTv, ),
pageBuilder: (context, state) => buildPageWithDefaultTransition( GoRoute(
context: context, state: state, child: const WelcomePage()), path: TvDetailsPage.route,
), pageBuilder: (context, state) => buildPageWithDefaultTransition(
GoRoute( context: context,
path: WelcomePage.routeMoivie, state: state,
pageBuilder: (context, state) => buildPageWithDefaultTransition( child: TvDetailsPage(seriesId: state.pathParameters['id']!)),
context: context, state: state, child: const WelcomePage()), ),
), GoRoute(
GoRoute( path: SearchPage.route,
path: TvDetailsPage.route, pageBuilder: (context, state) => buildPageWithDefaultTransition(
pageBuilder: (context, state) => buildPageWithDefaultTransition( context: context,
context: context, state: state,
state: state, child: SearchPage(query: state.uri.queryParameters["query"])),
child: TvDetailsPage(seriesId: state.pathParameters['id']!)), ),
), ]),
GoRoute( StatefulShellBranch(routes: [
path: MovieDetailsPage.route, GoRoute(
pageBuilder: (context, state) => buildPageWithDefaultTransition( path: WelcomePage.routeMoivie,
context: context, pageBuilder: (context, state) => buildPageWithDefaultTransition(
state: state, context: context, state: state, child: const WelcomePage()),
child: MovieDetailsPage(id: state.pathParameters['id']!)), ),
), GoRoute(
GoRoute( path: MovieDetailsPage.route,
path: SearchPage.route, pageBuilder: (context, state) => buildPageWithDefaultTransition(
pageBuilder: (context, state) => buildPageWithDefaultTransition( context: context,
context: context, state: state,
state: state, child: MovieDetailsPage(id: state.pathParameters['id']!)),
child: SearchPage(query: state.uri.queryParameters["query"])), ),
), ]),
GoRoute( StatefulShellBranch(routes: [
path: SystemSettingsPage.route, GoRoute(
pageBuilder: (context, state) => buildPageWithDefaultTransition( path: ActivityPage.route,
context: context, pageBuilder: (context, state) => buildPageWithDefaultTransition(
state: state, context: context, state: state, child: const ActivityPage()),
child: const SystemSettingsPage()), ),
), ]),
GoRoute( StatefulShellBranch(routes: [
path: ActivityPage.route, GoRoute(
pageBuilder: (context, state) => buildPageWithDefaultTransition( path: SystemPage.route,
context: context, state: state, child: const ActivityPage()), pageBuilder: (context, state) => buildPageWithDefaultTransition(
), context: context, state: state, child: const SystemPage()),
GoRoute( )
path: SystemPage.route, ]),
pageBuilder: (context, state) => buildPageWithDefaultTransition( StatefulShellBranch(routes: [
context: context, state: state, child: const SystemPage()), GoRoute(
) path: SystemSettingsPage.route,
pageBuilder: (context, state) => buildPageWithDefaultTransition(
context: context,
state: state,
child: const SystemSettingsPage()),
),
]),
], ],
); );
final router = GoRouter( final router = GoRouter(
navigatorKey: APIs.navigatorKey, navigatorKey: APIs.navigatorKey,
initialLocation: WelcomePage.routeTv,
routes: [ routes: [
shellRoute, shellRoute,
GoRoute( GoRoute(
@@ -154,7 +158,7 @@ class _MyAppState extends ConsumerState<MyApp> {
} }
class MainSkeleton extends StatefulWidget { class MainSkeleton extends StatefulWidget {
final Widget body; final StatefulNavigationShell body;
const MainSkeleton({super.key, required this.body}); const MainSkeleton({super.key, required this.body});
@override @override
@@ -164,23 +168,11 @@ class MainSkeleton extends StatefulWidget {
} }
class _MainSkeletonState extends State<MainSkeleton> { class _MainSkeletonState extends State<MainSkeleton> {
var _selectedTab;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var uri = GoRouterState.of(context).uri.toString();
if (uri.contains(WelcomePage.routeTv)) {
_selectedTab = 0;
} else if (uri.contains(WelcomePage.routeMoivie)) {
_selectedTab = 1;
} else if (uri.contains(ActivityPage.route)) {
_selectedTab = 2;
} else if (uri.contains(SystemSettingsPage.route)) {
_selectedTab = 3;
} else if (uri.contains(SystemPage.route)) {
_selectedTab = 4;
}
var padding = isSmallScreen(context) ? 5.0 : 20.0;
return AdaptiveScaffold( return AdaptiveScaffold(
appBarBreakpoint: Breakpoints.standard, appBarBreakpoint: Breakpoints.standard,
appBar: AppBar( appBar: AppBar(
@@ -258,23 +250,8 @@ class _MainSkeletonState extends State<MainSkeleton> {
], ],
), ),
useDrawer: false, useDrawer: false,
selectedIndex: _selectedTab, selectedIndex: widget.body.currentIndex,
onSelectedIndexChange: (int index) { onSelectedIndexChange: (p0) => widget.body.goBranch(p0),
setState(() {
_selectedTab = index;
});
if (index == 0) {
context.go(WelcomePage.routeTv);
} else if (index == 1) {
context.go(WelcomePage.routeMoivie);
} else if (index == 2) {
context.go(ActivityPage.route);
} else if (index == 3) {
context.go(SystemSettingsPage.route);
} else if (index == 4) {
context.go(SystemPage.route);
}
},
destinations: const <NavigationDestination>[ destinations: const <NavigationDestination>[
NavigationDestination( NavigationDestination(
icon: Icon(Icons.live_tv_outlined), icon: Icon(Icons.live_tv_outlined),
@@ -302,7 +279,11 @@ class _MainSkeletonState extends State<MainSkeleton> {
label: '系统', label: '系统',
), ),
], ],
body: (context) => SafeArea(child: widget.body), body: (context) => SafeArea(
child: Padding(
padding: EdgeInsets.only(
left: padding, right: padding, top: 5, bottom: 5),
child: widget.body)),
// Define a default secondaryBody. // Define a default secondaryBody.
// Override the default secondaryBody during the smallBreakpoint to be // Override the default secondaryBody during the smallBreakpoint to be
// empty. Must use AdaptiveScaffold.emptyBuilder to ensure it is properly // empty. Must use AdaptiveScaffold.emptyBuilder to ensure it is properly
@@ -318,13 +299,11 @@ class _MainSkeletonState extends State<MainSkeleton> {
return AlertDialog( return AlertDialog(
title: Text("项目开发不易,给开发者加个鸡腿:"), title: Text("项目开发不易,给开发者加个鸡腿:"),
content: SizedBox( content: SizedBox(
width: 350, width: 350,
height: 400, height: 400,
child: child: Ink.image(
Ink.image( fit: BoxFit.fitWidth,
fit: BoxFit.fitWidth, image: AssetImage("assets/wechat.jpg")) image: AssetImage("assets/wechat.jpg"))),
),
); );
}, },
); );