Flutter - Navigator.pushReplacementNamed 显示相同的页面
Flutter - Navigator.pushReplacementNamed show the same page
我有一个简单的应用程序,它有一个 OnBoarding 部分,最后我只想用主页替换当前屏幕。
我安装了 this package 以避免自己重新创建入职逻辑并且似乎运行良好,但无法弄清楚为什么最后我实现 onDone
功能时它向我展示同屏。
这是我的 main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sizer/sizer.dart';
// Application
import './theme.dart';
import './routes.dart';
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool shoudShowOnboardingPage =
sharedPreferences.getBool('shoudShowOnboardingPage') ?? true;
runApp(
MyApp(
shouldShowOnBoardingScreen: shoudShowOnboardingPage,
),
);
}
class MyApp extends StatelessWidget {
final bool shouldShowOnBoardingScreen;
MyApp({
this.shouldShowOnBoardingScreen,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return OrientationBuilder(
builder: (context, orientation) {
SizerUtil().init(constraints, orientation);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'My app',
theme: themeData,
home: shouldShowOnBoardingScreen
? OnBoardingScreen()
: HomePageScreen(),
onGenerateRoute: RouteGenerator.generateRoute,
);
},
);
});
}
}
这是我的 routes.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// Application
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';
class RouteGenerator {
static const String homePage = '/';
static const String onBoardingPage = '/onboarding';
RouteGenerator._();
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case homePage:
return MaterialPageRoute(
builder: (_) => HomePageScreen(),
);
case onBoardingPage:
return MaterialPageRoute(
builder: (_) => OnBoardingScreen(),
);
default:
throw FormatException('Route not found');
}
}
}
My onBoarding(存储库仅定义页面的标题、body 和图像):
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sizer/sizer.dart';
// Application
import '../../repositories/onboarding/onboarding_repository.dart';
import '../../models/onboarding/onboarding_page.dart';
import '../../routes.dart';
class OnBoardingScreen extends StatelessWidget {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
@override
Widget build(BuildContext context) {
OnBoardingRepository onBoardingRepository = OnBoardingRepository();
return Scaffold(
body: IntroductionScreen(
globalBackgroundColor: Colors.black,
pages: List.generate(
onBoardingRepository.pages.length,
(index) =>
buildPageViewModel(onBoardingRepository.pages[index], context),
),
showSkipButton: true,
skip: Text(
'Salta',
style: TextStyle(
color: Colors.white,
),
),
next: const Icon(
Icons.arrow_forward,
color: Colors.white,
),
done: Container(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 6,
),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border.all(
color: Theme.of(context).primaryColor,
),
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: Text(
'Fine',
style: TextStyle(
color: Colors.white,
),
),
),
onDone: () async {
final SharedPreferences sharedPreferences = await _prefs;
sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
});
},
dotsDecorator: DotsDecorator(
activeColor: Theme.of(context).primaryColor,
size: const Size.square(10.0),
activeSize: const Size(20.0, 10.0),
color: Colors.white,
spacing: const EdgeInsets.symmetric(horizontal: 3.0),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
),
),
);
}
PageViewModel buildPageViewModel(
OnBoardingPage onBoardingPage, BuildContext context) {
return PageViewModel(
title: onBoardingPage.title,
body: onBoardingPage.body,
image: Padding(
padding: EdgeInsets.only(top: 10.0.h),
child: Center(
child: SvgPicture.asset(
onBoardingPage.image,
height: 60.0.w,
),
),
),
decoration: PageDecoration(
titleTextStyle: TextStyle(
fontSize: 16.0.sp,
fontWeight: FontWeight.w700,
color: Theme.of(context).primaryColor,
),
bodyTextStyle: TextStyle(fontSize: 13.0.sp, color: Colors.white),
),
);
}
}
这里是 home.dart
import 'package:flutter/material.dart';
class HomePageScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('hello'),
),
);
}
}
入门部分运行良好,我可以看到页面,浏览它们。问题是当我按下 done
按钮并调用 onDone
函数时,它从头开始一次又一次地显示入职屏幕。
我期望的是在我为我的 shoudShowOnboardingPage
设置设置布尔值后删除登机屏幕并将其替换为主页。
这里有一段代码不符合我的预期:
onDone: () async {
final SharedPreferences sharedPreferences = await _prefs;
sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
});
},
我错过了什么?
因为您在 MaterialApp
中指定了 home
小部件,当您导航到空 \
路线时,它将再次显示 home
小部件。
我建议您 MaterialApp
使用 initialRoute
。
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'My app',
theme: themeData,
initialRoute: shouldShowOnBoardingScreen
? RouteGenerator.onBoardingPage
: RouteGenerator.home,
onGenerateRoute: RouteGenerator.generateRoute,
)
我有一个简单的应用程序,它有一个 OnBoarding 部分,最后我只想用主页替换当前屏幕。
我安装了 this package 以避免自己重新创建入职逻辑并且似乎运行良好,但无法弄清楚为什么最后我实现 onDone
功能时它向我展示同屏。
这是我的 main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sizer/sizer.dart';
// Application
import './theme.dart';
import './routes.dart';
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool shoudShowOnboardingPage =
sharedPreferences.getBool('shoudShowOnboardingPage') ?? true;
runApp(
MyApp(
shouldShowOnBoardingScreen: shoudShowOnboardingPage,
),
);
}
class MyApp extends StatelessWidget {
final bool shouldShowOnBoardingScreen;
MyApp({
this.shouldShowOnBoardingScreen,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return OrientationBuilder(
builder: (context, orientation) {
SizerUtil().init(constraints, orientation);
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'My app',
theme: themeData,
home: shouldShowOnBoardingScreen
? OnBoardingScreen()
: HomePageScreen(),
onGenerateRoute: RouteGenerator.generateRoute,
);
},
);
});
}
}
这是我的 routes.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// Application
import './screens/home/home.dart';
import './screens/onboarding/onboarding.dart';
class RouteGenerator {
static const String homePage = '/';
static const String onBoardingPage = '/onboarding';
RouteGenerator._();
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case homePage:
return MaterialPageRoute(
builder: (_) => HomePageScreen(),
);
case onBoardingPage:
return MaterialPageRoute(
builder: (_) => OnBoardingScreen(),
);
default:
throw FormatException('Route not found');
}
}
}
My onBoarding(存储库仅定义页面的标题、body 和图像):
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sizer/sizer.dart';
// Application
import '../../repositories/onboarding/onboarding_repository.dart';
import '../../models/onboarding/onboarding_page.dart';
import '../../routes.dart';
class OnBoardingScreen extends StatelessWidget {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
@override
Widget build(BuildContext context) {
OnBoardingRepository onBoardingRepository = OnBoardingRepository();
return Scaffold(
body: IntroductionScreen(
globalBackgroundColor: Colors.black,
pages: List.generate(
onBoardingRepository.pages.length,
(index) =>
buildPageViewModel(onBoardingRepository.pages[index], context),
),
showSkipButton: true,
skip: Text(
'Salta',
style: TextStyle(
color: Colors.white,
),
),
next: const Icon(
Icons.arrow_forward,
color: Colors.white,
),
done: Container(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 6,
),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border.all(
color: Theme.of(context).primaryColor,
),
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
child: Text(
'Fine',
style: TextStyle(
color: Colors.white,
),
),
),
onDone: () async {
final SharedPreferences sharedPreferences = await _prefs;
sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
});
},
dotsDecorator: DotsDecorator(
activeColor: Theme.of(context).primaryColor,
size: const Size.square(10.0),
activeSize: const Size(20.0, 10.0),
color: Colors.white,
spacing: const EdgeInsets.symmetric(horizontal: 3.0),
activeShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
),
),
);
}
PageViewModel buildPageViewModel(
OnBoardingPage onBoardingPage, BuildContext context) {
return PageViewModel(
title: onBoardingPage.title,
body: onBoardingPage.body,
image: Padding(
padding: EdgeInsets.only(top: 10.0.h),
child: Center(
child: SvgPicture.asset(
onBoardingPage.image,
height: 60.0.w,
),
),
),
decoration: PageDecoration(
titleTextStyle: TextStyle(
fontSize: 16.0.sp,
fontWeight: FontWeight.w700,
color: Theme.of(context).primaryColor,
),
bodyTextStyle: TextStyle(fontSize: 13.0.sp, color: Colors.white),
),
);
}
}
这里是 home.dart
import 'package:flutter/material.dart';
class HomePageScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('hello'),
),
);
}
}
入门部分运行良好,我可以看到页面,浏览它们。问题是当我按下 done
按钮并调用 onDone
函数时,它从头开始一次又一次地显示入职屏幕。
我期望的是在我为我的 shoudShowOnboardingPage
设置设置布尔值后删除登机屏幕并将其替换为主页。
这里有一段代码不符合我的预期:
onDone: () async {
final SharedPreferences sharedPreferences = await _prefs;
sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
});
},
我错过了什么?
因为您在 MaterialApp
中指定了 home
小部件,当您导航到空 \
路线时,它将再次显示 home
小部件。
我建议您 MaterialApp
使用 initialRoute
。
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'My app',
theme: themeData,
initialRoute: shouldShowOnBoardingScreen
? RouteGenerator.onBoardingPage
: RouteGenerator.home,
onGenerateRoute: RouteGenerator.generateRoute,
)