Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
413 views
in Technique[技术] by (71.8m points)

Flutter - Navigator.pushReplacementNamed show the same page

I have a simple app that has a OnBoarding section and at the end I just want to replace the current screen with the home.

I have installed this package to avoid to recreate myself the onboarding logic and seems to work well, but can't figured out why at the end when I implement the onDone function it shows me the same screen.

Here my 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,
          );
        },
      );
    });
  }
}

Here my 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 (the repository just define title, body and image for the pages):

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),
      ),
    );
  }
}

And here the home.dart

import 'package:flutter/material.dart';

class HomePageScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('hello'),
      ),
    );
  }
}

The onboarding section works well, I can see the pages, navigate them. The problem is when I press the done button and invoke the onDone function it shows again and again the onboarding screen from the beginning.
What I expect is to remove the onBoarding screen and replace it with the home just after I set the boolean value for my shoudShowOnboardingPage setting.

Here the piece of code that do not work as I expect:

onDone: () async {
        final SharedPreferences sharedPreferences = await _prefs;
        sharedPreferences.setBool('shoudShowOnboardingPage', false).then((_) {
        Navigator.of(context).pushReplacementNamed(RouteGenerator.homePage);
   });
},

What am I missing?

question from:https://stackoverflow.com/questions/65888174/flutter-navigator-pushreplacementnamed-show-the-same-page

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Because you have specified the home widget in your MaterialApp when you navigate to the route empty route, it will display the home widget again.

I suggest you have the MaterialApp use initialRoute.

MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'My app',
   theme: themeData,
   initialRoute: shouldShowOnBoardingScreen
            ? RouteGenerator.onBoardingPage
            : RouteGenerator.home,
   onGenerateRoute: RouteGenerator.generateRoute,
)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...