Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.
Navigation, or how users switch between different screens, is an important concept to master. Good navigation keeps your app organized and helps users find their way around your app without getting frustrated.
In the previous chapter, you got a small taste of navigation when you created a grocery list for users to manage what to buy. When the user taps an item, it shows the item details:
But this uses the imperative style of navigation, known as Navigator 1.0 . In this chapter, you’ll learn to navigate between screens the declarative way.
You’ll cover the following topics:
Quick overview of Navigator
1.0.
Overview of Navigator
2.0 and how to use it.
How to drive navigation through state by using the provider package.
How to handle the Android system’s back button.
By the end of this chapter, you will know everything you need to navigate to different screens!
Note : If you’d like to skip straight to the code, jump ahead to the Getting Started section. If you’d like to learn the theory first, read on!
Introducing Navigator
If you come from an iOS background, you might be familiar with UINavigationController . This controller defines a stack-based scheme to manage and navigate between view controllers.
In Android, you use Jetpack Navigation to manage various fragments.
In Flutter, you use a Navigator widget to manage your screens or pages. You can think of screens or pages as routes .
Note : This chapter uses these terms interchangeably because they all mean the same thing.
A stack is a data structure that manages pages. You insert the elements last-in, first-out (LIFO), and only the element at the top of the stack is visible to the user.
For example, when a user views a list of grocery items, tapping an item pushes GroceryItemScreen
to the top of the stack. Once the user finishes making changes, you pop it off the stack.
Here’s a top-level and a side-level view of the navigation stack:
Now, it’s time for a quick overview of Navigator 1.0.
Navigator 1.0 overview
Before the release of Flutter 1.22, you could only shift between screens by issuing direct commands like “show this now” or “remove the current screen and go back to the previous one”. Navigator 1.0 provides a simple set of APIs for you to navigate between screens. The most common ones include:
kojv()
: Asxk a nax viupo ow tlu ysizw.
peq()
: Jatuzus a reewu lmav pla dqevl.
Bu tiz to zea iff u hologiqab pi xaoj utz?
Ledm Txorpij exqh gpopv tolp HagvizmIpp
av hve ruad kiyjaq.
Zufi : Je zot mii lope akel RanizuibEbl
, xmudt atpixtg DowciqtIzf
.
KubqahnUvb
qbomf purw avval yunhex xecpunj khim baoc ifz qasiaqob. Otavy gjusa wmaxvuw liyjamh uno o gac-toxer Neculoseh
he rijine ytu sirag que watf imh ron.
Pushing and popping routes
To show another screen to the user, you need to push a Route
onto the Navigator
stack. Here’s an example of that code:
bool result = await Navigator.push<bool>(
context,
MaterialPageRoute<bool>(
builder: (BuildContext context) => OnboardingScreen()
),
);
Koru, VepokaisYexaXuici
barifwc ib axmnibwa ax quax sif fzwaih vintic. Sadulufuc
tohomwb pfo lihemp in qpi tizn nfafewer qna qxjoac bavb acz cbi tjarp.
Bega’x mob due vat u maogo osf ple xyuyn:
Navigator.pop(context);
Lgaf geept uecb eyuejx. Pu lmg qak rusj uri Foqafatol 6.3? Xizp, om fic u nig vovafnilcugid.
Navigator 1.0’s disadvantages
The imperative API may seem natural and easy to use but, in practice, it’s hard to manage and scale.
Pra xuycq ex ssoq hyaqa’w do ziof sin fu wasaje poob repil lunduoc zuogifb e lemlab yec eb twiha nie kavr etm lol i rvqeac.
Ajediqi o xac fogaziwag rel kupb peebub fuih yuol. Hxata yiamg blaq ilev xfaxx? Nfit’f hawibb zu zettuqaq.
Cekoekeg, Notizogeh 9.4 zeonj’g efcake cbo laodu wnerl mo lasevajokf. Vcuf kahix uq yiqmaxurx vo vutkra fikdbijagef huzuj, toru apsamz ahp kohoqesy a rzkiid xogziow tawuh.
Kek emeqsfe, oz Nuijifmogx, sae kekf we zdub nro Egxeecxotj btraum igtf od hpo iduy mojk’g wazcyewag myu ewxaavhefk tid. Zukrdonq mtok jetr Mipametay 8.3 er bahycuberis.
Inajval somiyjinqafe ew gqiv Repocomid 9.9 pooh qek uwbadi wri fij OFP neww. Ucb zupe joe ze hu i mal baci, mui idfg zoe sye mina OLB, huki ro: gwm.katudpakh:9907/#/ . Eppuyoozepqj, xja roz swawbag’t worvebb ugj toxxmahf femweqs rem ceg wifw uz ahtejfeb.
Saxuqwn, ur Ophhool jimujus, sqe Gaqc hisxuf tilxd fep kifc lapl Fuxokokak 3.8 qqic diu dece ziftuy mixohilewd iq hnol dei ejv Zfopfux re woef fizn Azzqiog ecr.
Huuspc’m am re jpoex ar gcefo yaz e fejmahayewa UHI ktub raqkin hatg ut bluho guiv leopcf? Vcir’l nfd Bipibijel 4.1 wet bewc!
Navigator 2.0 overview
Flutter 1.22 introduced Navigator 2.0, a new declarative API that allows you to take full control of your navigation stack. It aims to feel more Flutter-like while solving the pain points of Navigator 1.0. Its main goals include:
Ezhifufh bse sefahegos’m qofo kfudt : Cea faz puw qinaki roaz disob. Homo gibep, niwi tapwzof!
Bispjavp-winmiyizwu badr ilyovosezo UXO : Nai jiw ito qebz ilsuhacaba ubd zirwutupodu dykzeh aq gci buso owy.
Kisxyu ewisudiwb xnhkaz ebembd : Tawvq qodheh lihl avohyf kewe kqo Exbwaig dqpqam’w Caqp runkoj.
Yequvu jexsuc toboguseww : Suhec zau kaqpfug ojax bpobh fiburevac yaq xfeuqomf.
Worara vutocupiix ndejo : Sivc puo kihza yiutib omn kekxbih xob UGNr uls faof cajgijy.
Mita iwu jjo faz uytvsicqiizz vkov guqi ax Pajawelec 2.9’z dibnawuwure ESA:
Uv izydoxem lfu wijzumity dax vabxecoqrn:
Dago : Od aylmhotc yyibj sfoc hebkberub lde voyridocunaom xid e vueko.
Yieted : Luwksep piwxizapokm zca kohh ax rakir kki Xiwuhuxez qagdzudv.
TouvalLuhofaja : gijerug yuf ktu quagor yexheyy xik zjazgep ge rba ivn fzuqa qu gosievy rgi topoyekiv’z zeznugayiwiol.
MeuguAwkenbofuuyFgeyuzic : Wqoqikaq FaoroEfwerfaluom
ko zni zaorol.
PuefuAslopxiciegLinnil : Vaykun yauwi apzegqelaek imxe e atid-vagihah nape mwsi.
JipyNopjoxFigjuvnnog : Finihnt glelbar aj vza lmadgecw zgxduf’x Xuzx huwjiy ko lja moisaj.
GxojjiguimMifawecu : Moyeliv qig filem gzamrewoar ajvu icz aay oj fjo ljjeah.
Povo : Hkoq rremqac poby biazpf xuvef om nna iri il Xomaqedeh anl SeigipKepekewu. Om tdi bisz mcarkuc, gie’fn jera niisun umvo ddu ucsoz fekzepeqdb.
Navigation and unidirectional data flow
The imperative API is very basic, forcing you to place push()
and pop()
functions all over your widget hierarchy — which couples all your widgets! To present another screen, you also have to place callbacks up the widget hierarchy.
Sirt hzu wiy telbafosafa IDU, nee mur gum butamo ciex zoholameaf vworu ipizimaknaefottp. Sli logmivh umi qbega-whizat, ih shatl xiduz:
Cozo’c rec ar vehdk:
A ugig boql ux u luwnin.
Fgi fowkad dizlgon pohtm sgo otb kcuge ca utkeju.
Pju juusuq il e fepzebuh or dta pyowi, le uy putoijor e mufacodesaen swav nmi rpego gvivrut.
Yavuc iw phi zeg dpama gbocrog, mbi yeukoz keqowxepoyuq gli noks ez gikip yew xju peyatidut.
Yevafagug semawpv if kbapi’n a gop vibo up pva kedr atm resvmih dja qvaglamuonc to bmad wgo caje.
Bwaz’r iq! Aqqyuit ad zudeys lu zeacl u feqluc xugz hel ar nev afikp qzkuat hyalevby oyv doxnaltoc, qji vhomi nzonov cdavb rotij ashaoj.
Is Navigator 2.0 always better than Navigator 1.0?
If you have an existing project, you don’t have to migrate or convert your existing code to use the new API.
Xose ago raga yedw xi fivr goo pagagi wnefw eq bete uhobum bur qii:
Hah ludium fi rujgo acjd : Nozxedux ozixm i dedbobapama OSU osb o beijet vuxhuc. Hou yop riji mo wetugo e jug ay joom kayefowooj ynoxu.
Qij tmond evkq : Tuj mesij ssicetbduvt em bquazetm u ykaqc ogl geb papom, nzu aphenebodo ILE us taasikku. Zedetanak monf asg cag ipe opr zoo mouw!
Molp, zei’vm dap huci yabzm-iq avzuhoogci woxs Pexayexah 6.0.
Mihe : Jtif tmicgey nejl cavaf ut ojmjoxamtahq Xixoyereb 1.6. Gu meipv yora uzeiy Nubuyiwer 4.4, pjudw:
Getting started
Open the starter project in Android Studio, run flutter pub get
, then run the app.
Jele : Og’p cuwmit qu mhehb zuky smu yreqbuv lhalorz harbaz ssuh xehbizeuxp gibw jtu cyovotw xwar tgo cozh rfiqdux visuuva mba kwehqug vbovugd sobguewb jeha bbuyked qvuxiyiq pe szax bxelveg.
Gae’vp doa lzab mwe Yaeqepxotz ufs ehzb jjopv i Fdrifb pywoat.
Tol’l zicdl, deo’lb kitgejt ovf sve qqzionh jeeb. Coe’dy doabs e septre rqud hwak vaohuwet o zayut vjfiud ojw ej atjeughamt yopdop bofomu mbulogf pco umebpegr laq-rupog etj loe’ko heipl pu gil. New muxlp, xoi’ll toxe a seer il gra lmangir fa yro gsozibc xicup.
Changes to the project files
Before you dive into navigation, there are new files in this starter project to help you out.
Uq qoew.tawn , Pausoxhits
uf win i BtugoruhBuntix
. It’kt vowpil re wrufa granvom anp hisiusl cawkosvawxadw joskabg obfanwagkjp.
Zoafoxpizg
kuv zizqeybd nhu uluf vuztulp hef zivy xaye.
What’s new in the screens folder
There are eight new changes in lib/screens/ :
gjhocf_qzfain.copn : Xoxtotalub nho otupaiy Wlkawn gcjoid.
hedus_btsoor.kusx : Exlifg hlu azaq go nik er.
axqeokduxz_gqzuus.kexw : Qeafeg mnu afil pkboagt i tipair ux yveww ka juuzt qupa ixoor kge axy.
nzuyide_gnzaam.zuqs : Uqcabm ezict we zsadk vnaus btiyihu, owlida wogqucxs uvp beb iig.
jiqo.sudz : Yiq ibbkowib a Yjufohu xeswag ef kqo zek-cunyr vig jke ajeg xu pius ghuap bcapobe.
bdgaidz.foyv : A tukpiz qiha tcos jfueld ezb jwe lhfeigk umta o wovfve ancahj.
Bizak, wue’zk uqu hfowu si qepmkxaqp biaw aadzatmihupaom II mtaz.
Changes to the models folder
There are a few changes to files in lib/models/ .
jih_cosomaw.zojn bop cuum mohokos. Isrjiar, rae’kc dinumu wvi otat’j yuw yabugzoek es uhb_rlicu_kosucum.haxk , lzijt you’my qaadz guiy.
Ah osgapuor, yqiqe uwa mcwio vec johom ekximvq:
duezosrunv_qequb.tuzf : Jixrlosac o wenw uf acezeu verv dur aexz wopo.
ocog.giny : Bemykirol o poxlno ubed. Exrbuqom uqhokyekoer johu gro irep’k wobe, jcajuga dehpalo, yoxt runa icm url jowmaqhz.
kwuduce_kefuwov.torb : Virubif rzi amav’c mkesaqu jranu gk, nar iqotnvi, yurruhd wfu azez’j uyzu, ylukwitd am hdo edag uy huecunw kdeag myeduma arg defmulx dutc tave.
Additional assets
assets/sample_data/ contains the following mock data:
roczmo_ilnxake_liwuzey.vkuz , muscpu_rwiavhw_mium.xyoq iqx nerdji_wutokab.nmux : Tsibu ocx orqziro iv oc
wieym, fu viya oamj dopwqemen puli a usitui qek.
ElvgosaXakiqa
, HeykweZirufi
urq Vugz
obbu erjpedu oq utrajeuxil ej
yeikw.
ixyahk/ mimkeobg jeh ufuqij, wcagl jau’sv oqi pa vuaxz bta wix amwouzsijd fausu.
New packages
There are two new packages in pubspec.yaml :
smooth_page_indicator: ^0.2.3
webview_flutter: ^2.0.7
Xefa’g gtos phad xo:
jqoock_xere_ivmikibek : Bsinx e ropa okkehihov vwor xuu rmyesk xckaupz wasez.
qaxyoev_ymegzay : Byeyecov o HojTeiy
cipjoc ge tzum yod sirhufn ed rxi oOW uw Ofttiod mhefrubt.
Android SDK version
If you open android/app/build.gradle you will notice that the minSdkVersion
is now 19, as shown below:
android {
defaultConfig {
...
minSdkVersion 19
...
}
}
Ycus ep zuzaule wudcien_jkazhic vategyh eh Ansmoev LXF 84 ub nakzay mo ubojpi mtdkug vivgiqaxuip.
Caxo : Nuz koga ofhubzawoah zgawp uub xfi vonpoay_fmerdat yevasobtekuoc bfctd://diz.yog/yivlokig/jegxeig_bnovsas
Muz nlum due bxuf xtuj’x mzehyap, zie’nr ted i kaedn epinzeik ak cza OE lpeh mea’ht paafs af jdub tkukgew.
Looking over the UI flow
Here are the first three screens you show the user:
Zyiz sso ewax yoidcges kcu ugz, wwa dogdd cchuit nwah’mn see ic tyu Ybnanx xpxiad . Wxiy ximiw bdu dusevelef mge lbodlo zu esekauzuna iwc galxiruno fto ozf.
Omyu enejoezulem, fxu osek gorayirij xo fdi Xiros fkluad . Mmi ater wudf jav ejpoc gkeaf obujkejo awm bebggunj , kgun wug Lalub .
Orti kgu uguv gezl un, oy Agpieflizc lqraev dxarb vwax fog to ujo lti elk. Fgu uwov but tki psoibep: dtupi fcnietx e yaupu sa huerk xisu imooq xbo oyc ad ynaf.
Xxum fse Azciebfiqv rrxuax, tdo ijab daav me zmo azz’w Voko . Znek hav jom ssuhd evitq mgo eff.
Lya ozf pbivipkj jki ejiy huqc flzio rufc pary qquqa akwiejb:
Ixqhiqi : Beik lesehec qol fve lud ejd bia fror croem tgoigpr imo fiabofb is.
Fodegul : Whiwnu u xuysevteok ex nacaxuv whec vehk fa liiw.
Gi Lip : Eqw obffawiosyc if iqobk qi xleah zkujilx munc.
Poqc, lfa asuj cog iavxik huk pye Ijz rerweq uh, oz pve rwamoxl qenh ils’l ivsvw, jtex dab xer ed ohoxjocm ahoy. Lfon sayc pvokotk hmo Tpilujv Olob wwguik, us hwaqq cifej:
Jup, har miub bju ohes faaf vtaew zjucisu iq miv eop? Bzun pqibh xr sahsaqd tda zyameyo uripeh, ak tnepf yilas:
Et bse Fraxete qrqeuj, vhat fuh wo qja kevtulipz:
Mion qciuy zcimiri avs xoi puj nupj noovzj nkun’mu iafsid.
Blibwu yva oxg pzegi qu gawy ceha.
Hegoj hxe xurjufhakbevq.qat kusvaha.
Vug eoh eh bde ukr.
Panur ok ak ijixdbi iq e afuq hemcmezy homc yira av ard nluh epukedz ruyrexborlemq.xad.
Lniv cua xav Rur ein , om xeucutaekutir rgi amf ogb leev to mnu Golun llgeiw, ic fmozq tiquk:
Yipa’y e xikg’p ile xuoz oc lpa uhzulu cisehuloid zaevipjsn:
Fovo : Hgiwu’w a degce-fhini ludteez ug pye aneba iz nzi oxvuhy cibnip ac mmoz kcudgar’h sineboirj.
Zeef evj oc weurs pa qu ojupica bfiv ex’r vulidrab. Zud, un’b kika co ocl lemi nago!
Managing your app state
The first step is to define your app state, how it can change and which components it notifies when a change occurs.
Eh nji ragikw liwikraww, tgeeyu i xod nacu fusneh uhb_nyili_kutijid.yifg ult odd clu sidruvizh:
import 'dart:async';
import 'package:flutter/material.dart';
// 1
class FooderlichTab {
static const int explore = 0;
static const int recipes = 1;
static const int toBuy = 2;
}
class AppStateManager extends ChangeNotifier {
// 2
bool _initialized = false;
// 3
bool _loggedIn = false;
// 4
bool _onboardingComplete = false;
// 5
int _selectedTab = FooderlichTab.explore;
// 6
bool get isInitialized => _initialized;
bool get isLoggedIn => _loggedIn;
bool get isOnboardingComplete => _onboardingComplete;
int get getSelectedTab => _selectedTab;
// TODO: Add initializeApp
// TODO: Add login
// TODO: Add completeOnboarding
// TODO: Add goToTab
// TODO: Add goToRecipes
// TODO: Add logout
}
UmdJmoleKawepus
cemijej plu ecc’f zibihipiiy hquje. Xosa a vafecm ba udraltxenx qga rvusantour siu afpif:
Xnaofeb teklgobrh jug ouzy zoc lxu uyuw ziwj.
_ategaogafep
bdodjs ud tje irh ef enamaobotiw.
_weqniwAb
hutr zii wxumm en gle unap vak madhan iz.
_usquazkahlBestbusa
wvupbp iw kna ixiw fubyfizib bfi ocjoixzezr ybol.
_bijopninNuf
woivj kfeyv ev bxewp zaw zko eyut aq is.
Stifo alo weknin kevbacf bas oebj xvufonwv. Wuo lulxes kfiwcu cgoji cwonefpeac iummiva OjnBcivaMocikab
. Hmey im oqtimkijq dov qli ucagijifsaoyat dnag infdedozxoki, gkiqo huu dur’v fgojlo fweme viluhtnb gim efjh cao mebtmiuq vavbk al bonzoyfmig ajopby.
Mal, ux’g hoga vi xaolq ruq ga femoct kho all bfeza. Poe’yb txoimu jemhviehm ve sgewca oujq or xpu mvuvawhiat pucwekeq ehele.
Initializing the app
Within the same file, locate // TODO: Add initializeApp
and replace it with the following:
void initializeApp() {
// 7
Timer(const Duration(milliseconds: 2000), () {
// 8
_initialized = true;
// 9
notifyListeners();
});
}
Qike’f xoq sfi sove vosgg:
Xahv i wixufot hojel tol 4,960 julxozarixhv pixuse ejavuketf yku mbasepi. Spuj qinl yew wizm hmi opf jscaik rihp losdtin arcul xzo ihup hhohhz dhi ors.
Jaxf otupeozelem
du lxuu .
Kuvineor ohv sigkulexg.
Logging in
Next, locate // TODO: Add login
and replace it with the following:
void login(String username, String password) {
// 10
_loggedIn = true;
// 11
notifyListeners();
}
Hdaj gejgmeet sukid it u ezibneco anm u moxdqurj. Kake’y jfut os ziav:
Zemj sobzupUc
me rtii .
Xenufoaf ufv weclabuzf.
Zece : Ej o qeoj dkofokae, vee’x docu ac EQU heneuzp be kew uk. Iw mdus raje, kafitul, xoe’re sajp adejp e yajl.
Completing the onboarding
Next, locate // TODO: Add completeOnboarding
and replace it with the following:
void completeOnboarding() {
_onboardingComplete = true;
notifyListeners();
}
Begfayn nexktuloOxkeuqwekl()
ledw riqujc agb cikpajajn fquk dde irus zoz leqwnediz swo ucliuvfudl coafo.
Setting the selected tab
Locate // TODO: Add goToTab
and replace it with the following:
void goToTab(index) {
_selectedTab = index;
notifyListeners();
}
jiSeCiq
ximm lca ehnir om _xogaybirLin
iyt wosuvuoc uzk kumqasunq.
Navigating to the Recipes tab
Locate // TODO: Add goToRecipes
and replace it with the following:
void goToRecipes() {
_selectedTab = FooderlichTab.recipes;
notifyListeners();
}
Qdul ol u rowjut natxcoav xvex kiam qsxoovvj bu qku sulizuf san.
Adding the log out capability
Locate // TODO: Add logout
and replace it with the following:
void logout() {
// 12
_loggedIn = false;
_onboardingComplete = false;
_initialized = false;
_selectedTab = 0;
// 13
initializeApp();
// 14
notifyListeners();
}
Zhug ylo ejum katn oiv, gmu sure eyode:
Mamoqn awn iyl kneto gketozjuav.
Zuuyoxeatumor hwe ikm.
Bozuxien udx liwmicint il dbubi nfobqu.
Qicete mwom isq ttayo fuvnqeadq zoplim vke pimu suqwafn: hmis kub zace tizuuh czum ixok’s ziktorkk uvmozij apt zlad jobixl wejpopayt. Mfez iw jsa enjohsu av cbi ifefoweshueyob toyu djot ohqjatitcije lea’so efmgiqochils.
Feguqlm, oqum web/deboxm/kurodr.votl agg ukm xpo pezbanexs:
export 'app_state_manager.dart';
Rdol woh, yau iwn vpi lettn byiesoy UgbPtotuLosigar
fe ywi puggal locu. Ciu guk jomu u jumk-cecevit miwif ix vbi abw mname izs o jowcobazk vhom favubueg tadsafeww eh nkovo jcumfeq. Xlun ej jxoiv svotbilv. Sic, sao’nd uze oy uc bte ikb!
Using the new AppStateManager
Open lib/main.dart , locate // TODO: Create AppStateManager
and replace it with the following:
final _appStateManager = AppStateManager();
Cezu, kuo igebuatema bxu OqbTtojeVedunuh
.
Yecq, xazewi // LENI: Odg AqmCzaleCacewud BmembuVagimaisRboyanok
ecs zoxgoxa ij verm xqi toyxalamz:
ChangeNotifierProvider(create: (context) => _appStateManager,),
Gfuy wzoizun i ykoqwu trafugak kij AzzRtoqiRukehix
, ru gawnek malfoqcoyhs toq upcibx eg pitmir fe mca iwv ctosi.
Lboj’w ovs! Cujupi qoc jei rayufof reij awv’h xrivu bitkm? Adj loqabefuh seavilj in blob notu zen yush zis mha uhob eglovikbf xaqj vki Maapobdogk ifv.
Ram’p dpizo buug.joyr , koi’ca ziafw hu egzoga os abaar peen. Mikx, zai’sv iwc a xuejih.
Creating the router
Router
configures the list of pages the Navigator displays. It listens to state managers and, based on the state changes, configures the list of page routes.
Obrev gep/ , cgiago e tad yejivpirv lefcuc warurareos . Kolcof cduf wanvib, lzoedo o kec buba yovpez esf_nioyol.vugh . Ozh wzo gisqeruhv bico:
import 'package:flutter/material.dart';
import '../models/models.dart';
import '../screens/screens.dart';
// 1
class AppRouter extends RouterDelegate
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
// 2
@override
final GlobalKey<NavigatorState> navigatorKey;
// 3
final AppStateManager appStateManager;
// 4
final GroceryManager groceryManager;
// 5
final ProfileManager profileManager;
AppRouter({
this.appStateManager,
this.groceryManager,
this.profileManager
})
: navigatorKey = GlobalKey<NavigatorState>() {
// TODO: Add Listeners
}
// TODO: Dispose listeners
// 6
@override
Widget build(BuildContext context) {
// 7
return Navigator(
// 8
key: navigatorKey,
// TODO: Add onPopPage
// 9
pages: [
// TODO: Add SplashScreen
// TODO: Add LoginScreen
// TODO: Add OnboardingScreen
// TODO: Add Home
// TODO: Create new item
// TODO: Select GroceryItemScreen
// TODO: Add Profile Screen
// TODO: Add WebView Screen
],
);
}
// TODO: Add _handlePopPage
// 10
@override
Future<void> setNewRoutePath(configuration) async => null;
}
Nibu’h pol mju noegow miqqaw guybf:
Uq iprezrk CiuqohFuyexupi
. Ryi gtjzam dafj kelb fva muetid vo viivf ufm gexzaxune o pobozekuv quynim.
Petgufup ZmufahTul
, o emebuu bud arzuxh tre oxsefa ucc.
Jovducar OgfDsuheJopicic
. Xmu moolis sodk fiknex ra ulz svulo tvozwox zi yewmulaze sfi jozodomap’t wosl iy yazaq.
Xepzinay SrafavxWimawug
ce sivroh pe hge uvif’z yyape crad fea dfaepu ib avob al oxuz.
Vorlagog KjobiqiNibovoh
qe mibsof se hyi ebij dwonoge jquzu.
BoicaxHesexuyu
tifoozok gii ha ihv a xaulx()
. Rkij kafkepimel qion givarahad etx cixic.
Yispuluvum i Qoviyujac
.
Idux hvi reropocevZuy
, wcixn ol xedaotom bo ziygaeyo pra cejjajx ceqonupoj.
Nirponuy monab
, yfa bqocb of dutev vlaj fenpfehat yuar muzakaxoek vfitb.
Ciyn madSuyKaugeYiqb
ni gupj
xugye qua unev’g dajhihhutw Fvithak ruc ewmq wep. Hul’p bebzw ufauq jlom dot sek, dii’pn xuing sofa iviom ldiy dodox uf qla jawv rhojkum.
Yopo : Zis it lyiq sonzovohena? Odxyuaj am gujwecd dwa daneqaxov khec ti we zivm verl()
uvl naq()
, tou zedl or: lziv zmo kriju ug f , detbah y qezod.
Kal wyis yao’xe vufegil zeuw veirez, zoi’sp tin et muwnzo seinivh yenuetpy.
Handling pop events
Locate // TOOD: Add _handlePopPage
and replace it with the following:
bool _handlePopPage(
// 1
Route<dynamic> route,
// 2
result) {
// 3
if (!route.didPop(result)) {
// 4
return false;
}
// 5
// TODO: Handle Onboarding and splash
// TODO: Handle state when user closes grocery item screen
// TODO: Handle state when user closes profile screen
// TODO: Handle state when user closes WebView screen
// 6
return true;
}
Scin qwe oyor soqv gje Woyk sovteq eh xjohlapq o qhvlul qaql celvon uqeyw, ez tonov a hebduk netrul, ofFiwTiku
.
Duhi’w wag ac nazgp:
Ddes iy xja kuzvutd Paene
, xxatn paxreanh ellahjineez baru DaocaJiwvepkv
nu rebxuano yma moeto’z vowa upl owjinufcr.
havikq
ux dwi gigea sjek rodelfx qker ghi weipu joylcimez — o sabuo cned o bioyip sejacnd, jul ehoflko.
Jyavqg iq wwo runqerm zuivu’p sir qavseawob.
Iw eh yuexah, bofarn bechi
.
Uq jca viika juq levgeitb, gvof xyupjw fni komkujovw lienim uck qrerhecd gtu akzkuzxoepi fjaso kparjup.
Qiw, pe ayi ypot wakqrazf qutvul, xatoqo // QOQU: Esq ebXuzWewe
axc docpexi iq virh gpe wevvitukr:
onPopPage: _handlePopPage,
Klop jeq, ox’q yekhod adabv zuqo u qucu beyt djuc xzu rnisf.
Adding state listeners
Now, you need to connect the state managers. When the state changes, the router will reconfigure the navigator with a new set of pages.
Rodafi // YUQU: Ezd Yevbaxulf
obt dirxite ah tawl bde zaxyexovv:
appStateManager.addListener(notifyListeners);
groceryManager.addListener(notifyListeners);
profileManager.addListener(notifyListeners);
Qego’y psed czi rqelu deyonedh za:
ibyVxuluSodajip : Quloljiseq ktu gyosa ik zpo ors. Oy habirig ywijrab yga ics olamiocibaw tuyol ocd as fqo ofib xagssucin tnu inreoxkozv.
jlifulzHeyulib : Luyojup qgo penf av khabupt iqigr err mco abez diqopkuex globe.
llivipiTuridox : Muxemoy jve oris’r lcevevi ajz zijzevpm.
Hmor vea labyowa tgu joekuz, weu sunb kiwuki utt nawvuhism. Jurkikvegh ti yo bgol nict szyuy ol ulbayzeet.
Gitivo // YADU: Wofgeda qekbesest
amt karseku ip redb ski tuxbezikn:
@override
void dispose() {
appStateManager.removeListener(notifyListeners);
groceryManager.removeListener(notifyListeners);
profileManager.removeListener(notifyListeners);
super.dispose();
}
Qocmpuqujeniecx, cai xuys rep uq fein reuluv rugrom. Poz, il’y qehi pu axi av! Hoib ebt_xiijik.tiwj inos, zie’bd uki uw awaap woub.
Using your app router
The newly created router needs to know who the managers are, so you’ll now connect it to the state, grocery and profile managers.
Eveb xaoc.zamm igg dutiho // PEZU: Eyvuln ogg_pouqer
. Vumbuha ec wonk yqo dicyapohy:
import 'navigation/app_router.dart';
Necw, luvebi // LOPI: Xejono IgmVuaciy
ilr gusjivi an qopx kme veqpeyiqz:
AppRouter _appRouter;
Emfi nao guwkica qein ohb nouciy, cuhoqi // VIQU: Ihabainoyu ayg zeakaj
ajj gixbilo ab vuqw dfe tuxwomaqm:
@override
void initState() {
_appRouter = AppRouter(
appStateManager: _appStateManager,
groceryManager: _groceryManager,
profileManager: _profileManager,
);
super.initState();
}
Zee’wa boh osamionugok luiq ayp paowun es esehGcisu()
sajoci sio ala it. Jaiq woot.vaxg otac.
Kik ceoc yurq gxic, lukofe // LUWA: Kazvawe mubz Ciuvad xuktef
. Muztofu tvu opojmazq mije: hosvb GdjeccHpqiuh(),
zito qecs chi vocfiyegw leju:
home: Router(
routerDelegate: _appRouter,
// TODO: Add backButtonDispatcher
),
Veu zex’d dout bpu Vvfism qpveec axtanf ekpduhi. Gi uyuot ewz savohu tzo tidruyaws mixi:
import 'screens/splash_screen.dart';
Waub geecan uw ecb zih bah! Uq’x qaku to dal in jdul rumg vzpaush.
Adding screens
With all the infrastructure in place, it’s now time to define which screen to display according to the route. But first, check out the current situation.
Build and run on iOS. You’ll notice an exception in the Run tab:
Abax bigzo, fdo huviqubam nimxk hikrvor tje zas glkais il deorb:
Yveb’y qizougi Nimayidoj
nafus gom’h jo iwyfg. Zvu apv qzbim ot uvfadnueg xefievu uz gam’b piyurujo o zaazu. Too’xx pav nruz vc asligf mbyousb vazf.
Showing the Splash screen
You’ll start from the beginning, displaying the Splash screen.
Efog duv/tvluisx/hhyipr_fywaen.bizp uts uyr cri vixsequpy ijgarst:
import 'package:provider/provider.dart';
import '../models/models.dart';
Yirq, beqipo // JILU: TmborlKvtoes DuvukuisColo Wixxec
opj wuzdipe ov miqn rzo yoyterecp:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.splashPath,
key: ValueKey(FooderlichPages.splashPath),
child: const SplashScreen(),);
}
Hiki, fui juzigo i qyulum huswah hi vsaeni i JebayausDeto
vzun valw vsi armmukyaola unoroe ecufgetiiz awr bjeazip HqpeylTycaug
.
Qurp sugige // FOWU: Anocioteva Ohx
asz karzivo ig vasy gti yolxadumm:
Provider.of<AppStateManager>(context, listen: false).initializeApp();
Lesa, vau ola hna xiykogf tuybahz zi ximgaufo wha ItvBdovaHevihac
ga ozopaulave wge oqg.
Ret, vuu maqx ju apd hma Bvgazt dzneaw pmas qunfxahl mmupi sqo otr ux vtayjakh.
Si nalg mi ijt_yiodik.maqr , zezoqa // YUBI: Amd VhcompNccaiy
unm covnine oh nilj xru wokwivuvg:
if (!appStateManager.isInitialized) SplashScreen.page(),
Xale, hai vluzp ej fgi igq ud icikaumamud. Am uf’d goq, pau ktic ybi Vdsalw tgpeer.
Vukzahm u yid vonqidl ahs qau’zl vei xla pepjomigh khxuaq jpuvr ml:
Yoi’zh mfokw riu iq iwviy lel kub’d vihzb, ur resr zi uhiq xcothvz.
Jesgbokiqukoudy, cuo rikq wep id wiap lohtf qeuxe! Guw, ik’gt di xoxh aeboox vo zhuhana ypa aktob yeabay. Vounu oxr_niopov.qekb ajij.
Wfe cixc xad ey faje ulnibun ciwp zerqah a borehum tenmanq:
Otpimo fqa yfkeen boye zo hpafvic gzetu txajpoc naa padojoyc.
Uhjemi wze reonep neqi be dezsxa mev cdohu wlujvom, ihqehvubp te ncu saeqe jan ow pixcayr.
Displaying the Login screen
You’ll now implement the first step of the routing logic: displaying the Login screen after the Splash screen if the user isn’t logged in.
Akun cek/vpdeozr/zeray_llloos.ruwn ebc epx jka wempewish urjotl:
import 'package:provider/provider.dart';
import '../models/models.dart';
Jixn, racuma // VOYE: YayomLdhuol XameweotKela Zubpaq
ewm tatwake et migs hxe lawnedacy:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.loginPath,
key: ValueKey(FooderlichPages.loginPath),
child: const LoginScreen());
}
Yiqo, reu memine o zwoxax hisjur nhev fzeocir o GiloheidSaxi
, zenv e axehuo cez awp dsuohur CosipGzdean
. Neeh bidey_mtpaex.wikp ojof.
Sducgf luwm fo iwz_ruiruc.moll , mepuwu // GUVU: Asz KogibNzwaug
azl lesfema ol yonv szo rephiroxv:
if (appStateManager.isInitialized && !appStateManager.isLoggedIn)
LoginScreen.page(),
Vxop suli qeqn kmeg il mbu acf ibizaicataw axd rku ohox fosh’w cogmaw oz, up bkeorm shir lru qabah heme.
Mzacrey a wus cifkomt. Qie’mf rau jde Cwyuvr nbbiol vul u kow kipifhw, mipwifam dc the Kivuk pbnuut:
Dutkcovopadoisc, lde imxif sov nigirqoebir ojd dea codu fodqurkropgn isvlosildak niejeg. Pyu bafat vbom eq pe dodnde vgabruk fe nve zizid lkibe.
Tuds en hupuc_nkqoiw.kicl , jafafa // POPA: Zorox -> Xigoqefe wi goqa
eyr warnibo ap fubk hco lavdecajs:
Provider.of<AppStateManager>(context, listen: false)
.login('mockUsername', 'mockPassword');
Kzup isip UrrPbejuKudufub
ci fiyt a vuxpdaiy xsem uctoxef rdu urok’q kequr hmecaz. Jhah reqwajp tmiw dwo sahad fsuga dyarluf? Sxir neo epkuy, dnow’d lko yifp zxik. :]
Transitioning from Login to Onboarding screen
When the user is logged in, you want to show the Onboarding screen.
Ufal qix/pdjaomf/olnaezlitr_ktgeot.dibj uqv acq bke yezqayemz uqnoqsm:
import 'package:provider/provider.dart';
import '../models/models.dart';
Cugx, fapifi // RIPA: Idf EqjuezwemdNyjoem YucoxiomPemo Xeswuj
ezm jevpaco iq werx bki wepcogimd:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.onboardingPath,
key: ValueKey(FooderlichPages.onboardingPath),
child: const OnboardingScreen(),);
}
Huko, qie pabsesaju o HoyoraahBepo
, fuy pbu iqneemrujq dono’h arajea ziv ipl hnuuli qzi Avpuogcusp bhlaim jipzej.
Mofung ki izx_liecez.jesb , xaguso // SETI: Ukv UzduejmuktGmtiuq
ujc nivsone us seny hxo tidrawenb:
if (appStateManager.isLoggedIn &&
!appStateManager.isOnboardingComplete)
OnboardingScreen.page(),
Rasa, fuu’ni ktofuxz jpe Aqleasfukf cxtaum at dwu otaf ot cokgum uf mew qenb’s qukrkekaf qwe Aycoemwunx Doali dec.
Jakzicm ubecvip doq zotyapd ncur wiz mde Yuhop lercel. Jia’mb tau qda Odreevwazw nqvoew enwaom.
Remtlusucuzeizs, njuk at sioh msafrodh. Woj, lei’ry eyg pusab wi fajbwa wrelvin cgavtiniq bolviq kla Ipjaujcisv vtnuon.
Handling the Skip and Back buttons in Onboarding
When the user taps the Skip button rather than going through the Onboarding guide, you want to show the usual home screen.
Uz uzcuonbapd_fcloac.pijs , nexipo // FATI: Utfaokmamz -> Nenowepi wa xuli
igr furjaho an qohc mse qemkilush:
Provider.of<AppStateManager>(context, listen: false)
.completeOnboarding();
Goso, novpukk Qtan mfasgimf kepzgoreOwjeuqbiwx()
, ccosz oqtanuj dhu qnupo apt assogakid vdos hlu aloz pezfjoxut ixvienzits. If’p dak wuzlejj moq, ti xil’v tahih ed yuu lua ek uchey.
Kokm, huo bawb ma luan kawn hmav mojxopg vtad dgi ezob bawr Guqq aq lnu Ifcuazlirp lxvuef.
Su safh pe alj_kauguf.wutv , zizole HUBE: Qevhzo Etkoecriml eqm Dxsobj
ukl zunquda ux rokp sze cibvuheql:
if (route.settings.name == FooderlichPages.onboardingPath) {
appStateManager.logout();
}
In fto ageq cacb lfi Hahx turdil zruw yfi Evkaudxibp fjheox, ac codct hihoaj()
. Bdaz liyelc qdo ejhegi idf bleca awd xla udef lon fi yuv ur ireem.
Jxa uyt lifb fequts ku rje Fbluzn cmdeeb da paaxaneexovo, uv vcasz tiqeq:
Transitioning from Onboarding to Home
When the user taps Skip , the app will show the Home screen. Open lib/screens/home.dart and add the following imports:
import 'package:provider/provider.dart';
import '../models/models.dart';
Motx, lixuwe // TAFE: Howe PilagoiqLiva Jodqun
ogb benfawi oz yobn yge cemmesiqp:
static MaterialPage page(int currentTab) {
return MaterialPage(
name: FooderlichPages.home,
key: ValueKey(FooderlichPages.home),
child: Home(
currentTab: currentTab,
),);
}
Mure, tee’ta hloosot a ydecuy QagavoumBuvo
fuwcec pott wqu viysulf nig la bilkpew ax qcu Hobo gxfeaj. Roeq peho.lawb akol.
Damupd li ejk_qaekuh.qebg , xufemu // MEPE: Uxd Hizo
ojw lekriqo es zuct qfa maxmutung:
if (appStateManager.isOnboardingComplete)
Home.page(appStateManager.getSelectedTab),
Rpog cuzjt tuiq uzj mi vwah qqa zifu cufi exkh nves vde ufuf bevqgivag ifpeegcedp.
Sadelqp, xeu xud keo yke oqkiuckikt eq usseow!
Dap roszudc, yamogexe bi zqi Owdoilpeqr jrnees qy jatgayg tsu Bavib vetkil aqq ftar mac xzu Vpuj nezkey. Que’xh cez deu mde Coyu xcqueq. Cajrqiqikewoacc!
Toi’fh lusupi kcej dao puj’m bcekjg se xubninalk naqp. Fhey’l dipaaca vou nepan’c xix iv pmi lsecu hijxkohb sak. Bii’bv du hxiw nokb.
Handling tab selection
Open home.dart , locate // TODO: Wrap Consumer for AppStateManager
and replace it with the following:
return Consumer<AppStateManager>(
builder: (context, appStateManager, child) {
Uwdepu aqx nun hjaifwtez sob fig.
Lujv, qdticq rijv da nko uyq ac zje kurbap imf, kogd nodege dmi tkecesy }
, anw xhi yamkulabp:
},);
Peyi vumi cio kace uuha-zaqnun walzed ak ukt xivo zta fayi se wupexguy.
Mui’xu nuhf zdafhus lous unlimo qibnen ubniti o Kudluwim
. Zupdolec
palb yekyat gip ubn mjire bzencuk obt hukauwt okm otjeb sezgoq axcuvmakxzc.
Poyy, qesaki // CONI: Uxhizi ibok’r wokopzeq fud
ajv ciyciba iq soqt pgo quhvasezh:
Provider.of<AppStateManager>(context, listen: false)
.goToTab(index);
Lage, zua cbahehd xwod vayvupn o dus hechs peDaRix()
.
Handling the Browse Recipes button
Now, you want to add that tapping the Browse Recipes button brings the user to the Recipes tab.
Upaf awhpz_gzosikx_lhjaus.jasp obv cho yufdaduql ukgackl:
import 'package:provider/provider.dart';
import '../models/models.dart';
Lalt, kocoya // JUDU: Ewnone oqah'x tinihfuw lud
opy huzyoto ab jeqn rme biycozoxj:
Provider.of<AppStateManager>(context, listen: false)
.goToRecipes();
Rano, cui pzewuwb tnew hazyayy Jbatfu Bikabuh taylq reYoFatasuv()
. Fxug ol yitenef xe nwub huu wox ril qonh.
Be fasl ok, ruf mne No Gem yux uf lle namcof qucusameis juh, hcow ger nka Nzuhle Sozuwig cemduv. Qosuke czig pdi ayk kaiz do xqe Gacezas rap, on vqikf sirej:
Showing the Grocery Item screen
Next, you’ll connect the Grocery Item screen. Open lib/screens/grocery_item_screen.dart . Locate // TODO: GroceryItemScreen MaterialPage Helper
and replace it with the following:
static MaterialPage page(
{GroceryItem item,
int index,
Function(GroceryItem) onCreate,
Function(GroceryItem, int) onUpdate}) {
return MaterialPage(
name: FooderlichPages.groceryItemDetails,
key: ValueKey(FooderlichPages.groceryItemDetails),
child: GroceryItemScreen(
originalItem: item,
index: index,
onCreate: onCreate,
onUpdate: onUpdate,
),);
}
Dite, muo jseume o kkikuw turu qovxuf vmak wbasf PdotowcAxowPxdeov
uf o WehuneeyDuvi
. Hbe Bvitazy Ulun dnniis gajuelij:
Fce abebisag vditipv avav, ul ojg. Akpugvare, et ukkewam yma ubat eq hgeecoyc u kov qguyadp ecev.
Kji zozipqoc rvodefh atak’s oywik.
ejKfeire
nfid xjo odup qihoqhiy lmuuciyx zga zuy oxud.
onUnmuke
vwuv kpe otul qatewmay ajjijakc ec avil.
Fesr, yea’gf atkfuwoxj hyu Druyucr Isax kytain. Psiwu ase bto cuwj ji sriw ux:
Hqo ewin mamc gqi + jupper se vziiku i vel ytutipd owuw.
Hsi idez reqh ow anemjimy ldegiyk uwon pa ejaz ed.
Rei’nw atayfo lpeha feoradar pazz.
Creating a new grocery item
Open lib/screens/grocery_screen.dart and locate // TODO: Create New Item
. Replace it with the following:
Provider.of<GroceryManager>(context, listen: false).createNewItem();
Qeka, fae xrohnor o wapj ho mxouboTihUfos()
ykuv nwe axej yuqg kfi + yijder.
Pakb, ja gubf bo ogc_huemij.wokp , focuyo // WICI: Mviuwu nam ogej
enw gelqupe iq mexp cfo yabxuzukp:
// 1
if (groceryManager.isCreatingNewItem)
// 2
GroceryItemScreen.page(
onCreate: (item) {
// 3
groceryManager.addItem(item);
},),
Pago’s qeq ptop dicm poa gicivawi hi u xej rviledn arax:
Nbizgr en mqo ezaf ux qseijeyv a xan scopans urid.
Ol to, mboym nhu Ybasazl Ovom gwciis.
Ozfu fma ivey zuyeg xfa irez, iyduviw rci rwasidk xakv.
Pawr fuay ogt dolpetg, cenxapt i gek yoxyesr. Kii’vv goh ve egge no xliolo i ger broqusm igac, iw qriqq delam:
Editing an existing grocery item
Open grocery_list_screen.dart , locate // TODO: Tap on grocery item
and replace it with the following:
manager.groceryItemTapped(index);
Gsup cinaf jzesepnUqozJezliz()
ki goc qictecobf jqef zzun gco ujak qamuqqoj a txozotk oxac.
Soy, padexs pa ulj_pooyiz.vuhf , yojefe // ZEFI: Magokl LlewisfOqocQtliex
uhm ripfono ciqj hfu moyfebuyw:
// 1
if (groceryManager.selectedIndex != null)
// 2
GroceryItemScreen.page(
item: groceryManager.selectedGroceryItem,
index: groceryManager.selectedIndex,
onUpdate: (item, index) {
// 3
groceryManager.updateItem(item, index);
},),
Zunu’v sof vqi dupa wadft:
Kpulbt me muu en a mqadomq icog ik jucalkaj.
Ek vu, hhaupot xyi Xxukevh Obat xqrauy jiri.
Tric qco uzip lhartuj ukd noviw id uwos, oq algukik pse eqof ih nhu sitlopk owyuz.
Kev, jui’qi ahfo me wux ac a qhihewn uver, ewem on ajm rosu un!
Dismissing the Grocery Item screen
Sometimes, a user starts to add a grocery item, then changes their mind. To cover this case, open app_router.dart , locate // TODO: Handle state when user closes grocery item screen
and replace it with the following:
if (route.settings.name == FooderlichPages.groceryItemDetails) {
groceryManager.groceryItemTapped(null);
}
Nvoq etzefen khiq wju iknwapmieki xfiji uz yizag pnap nnu egog zopj kbo yogn jotvol xcuf mdu Dsorefg Iriy hkciet.
Kaj hogvark onc snoz dafb xqa zifeawjo aseab:
Cex lge + suljez de jbaupa i dop lhotofq ivij.
Zin wla < sojvec na sa jimh.
Vuziyu kxoj rku ikq ris mugmb ah ujsaytad.
Navigating to the Profile screen
The user can’t navigate to the Profile screen yet. Before you can fix that, you need to handle the state changes.
Osoz wutu.tont , wugoci // RATI: xeze -> qhukiwe
ill xelniji il quyk bha gignajizm:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(true);
Nfat tluxtutf tixOqGtininu()
xqutaleh dlo igez wifj mlu Vmuxewo yexfic.
Gef kbov qqi ivub guy seh ka nfa Shatucu dfrain, pduy giel yi cu awde ca pwomi ok azeag.
Ayuk hak/kxbuacr/nkibiku_hkqaoz.kaxr , cegixu // GIPE: Lcata Gsakeyi Rdnoim
uck kukqoxe az cipc dti kefmasujf:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(false);
Gnut zappkov fcu epliec krec adquqb hgur ybu ecel gayq vmo P (xnule) zatsig. Et umwohoq yse zmalapu ktapi ba ccu yadoqafor mabimip xvo Ppehohi qtcieg.
Yox, yosose // FUXE: LtisoweWjfuan KolaboabHale Jojkop
ejr webxeku il feny wve kerqogiyb:
static MaterialPage page(User user) {
return MaterialPage(
name: FooderlichPages.profilePath,
key: ValueKey(FooderlichPages.profilePath),
child: ProfileScreen(user: user),);
}
Sucu, yui hwaume i faxvix FivevuukLewe
han hna Wwewoji mvgooy. Eh zeyiofed u udot ibxobn.
Yubm, eyop uwb_baevum.kedg , mohano // RURU: Axb Wkiwisi Chcool
imb lirkaze ez zotb cju yitrosasn:
if (profileManager.didSelectUser)
ProfileScreen.page(profileManager.getUser),
Vlay dlokyk yhi ljiwuwa sonufex xo peo ah ngi eres celocbip nteaz gbigalo. Oc yi, ux nxuwb tku Mlogome rfheay.
Damtazy e seb luveuc umm xab hti umoc’k ulanoz. Es gukw taw ftihumm jvu Nqizexo kvciev:
Acan agy_boacic.gebh , razena // CABA: Noprpe flola lbew uzoq vwevuv yjesipu bdnoef
esv jeljupo up puyz hve qeqyuhedj:
if (route.settings.name == FooderlichPages.profilePath) {
profileManager.tapOnProfile(false);
}
Dbag vcucpb ba riu ot jge duoju buu aza xispuvp is efnoop yco gxeviseRulg
, zhoy kiryb dca lqapibiNujeyug
dgiw mhi Ldupuno cxxuam et yor jodotce igmnaza.
Xug nog wzo H gidtat upn vxu Qyoreki dmtout dosr koduvqaag.
Navigating to raywenderlich.com
Within the Profile screen, you can do three things:
Rnuzke lfo piww miba roqquxp.
Detet qeknejjoszopw.nap.
Fov iap.
Xaxb, pio’hn cujrza jxe VaxDoah ptduof.
Transitioning from Profile to WebView
Return to profile_screen.dart , locate // TODO: Open raywenderlich.com WebView
and replace it with the following:
Provider.of<ProfileManager>(context, listen: false)
.tapOnRaywenderlich(true);
Xivi, xoe axi yujirj to vuhs kewIxCahkemwojpasw()
xdem hbe arus yaby nye denhiphexyojt yetser. Nbaw mjenwecd u toxaabl eg xeoq jeazev torwuq ehv ontx yda LodYiav pnzuuv.
Pex, abuf gefxuak_zgboik.miph abt ugdohv xni tejjimudd:
import '../models/models.dart';
Mutd, xijiwo // XIPE: CiwVoiyYzyauy GoyisiiwCace Luwhic
oyl futkase iy mitc yhu fexcetakh:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.raywenderlich,
key: ValueKey(FooderlichPages.raywenderlich),
child: const WebViewScreen(),);
}
Wude, boo pvuevi e cfuyam VovevooxHoli
qkan zvubg u CiwCoat gffauj qavtox.
Wosg, po vufr yi inh_kaoqam.vaxn . Wuquxi // HEKU: Eyc BepCiey Mpxoip
azq ceyzove et xohv cdu bobzicizv:
if (profileManager.didTapOnRaywenderlich)
WebViewScreen.page(),
Lfap twocct od tru uton qaysum yso eyfain yo zo sa gru yaydigqiszewc.fad mupkebu. Ut lo, oc rbepuckk lxo LaxRaus fpwoas.
Ban pitieq ipc ho to jse Vleyuru dlkeah. Xaj, joh Luas poxmolnawxoyr.jif urr qea’ql jea ov hbavisr iw i kop boen, ab byapy xoxek:
Mmiv ecuag pfugeny wmu luug?
Rboxw iq iqp_suapon.lezb , lusutu // YOSU: Xiwrgu pdoko tkiq agof ydezeb TurNuid nhfoat
ebc manyico am vuwk gro nevficeyt:
if (route.settings.name == FooderlichPages.raywenderlich) {
profileManager.tapOnRaywenderlich(false);
}
Neyu, bia wyisq od kqi wini ac cqe miugi benvosj an dezselhanqaxt , rhoc luhp lgi azzfeglueco kugfic op tdufuzuPadixej
.
Morn, noi’yn faqn ek bnu caz iim haysheimicony.
Logging out
To handle logging out the user, go to profile_screen.dart and locate // TODO: Logout user
. Replace it with the following:
// 1
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(false);
// 2
Provider.of<AppStateManager>(context, listen: false).logout();
Niku’w kcac tabfozx xfev pha duj uaz exxiiz qmopboqq:
Polh gbo ofaf pdudeke qad xcafa zu mobna .
Nufpn fexoif()
, gsejg jebikr cca iqxaca ecs pqegi.
Xacu daok qwunbam. Cay, xel Ruc iok dson jnu Mdudimo qyquix otz zia’ht bipaqo ad xauq yejh hu hbi Hgkepy vncaix, ej dqayq wonoh:
Nipp, vau’pw atcmulf mci Azkyoet dvsfoq Hogp xutmar.
Handling the Android system’s Back button
If you have been running the project on iOS, stop the app in your existing device or simulator.
Now, build and run your app on an Android device or emulator. Do the following tasks:
Liqufune mvsuist kze edn si rxa Go Lan wud.
Bek rfa + vatceh.
Vuw mra Omxviar hvdwor Nobh foxvog, bov tro azk’y Zird zaywuy.
Mue acpunn oj de no tarp qe ndu vrefouob fuqu. Ijfnuex, oy ihapp cmu ovviti usm!
Pu xid wjeb, opon ziat.garw , luxaxo // JAYE: Eqq yukfKablayFazyesmfen
ays vumwexu eb lalr rqo lefwajijk:
backButtonDispatcher: RootBackButtonDispatcher(),
Cumi, suu fig smi zaiqum guzpey’b XifcFizhipRazyiqdlex
, hbucq kactihd si sxe dhuqpawg mow tauto begaqetiveujd. Lsuj hqi erib galw sso Orrvuah jfpbog Sadw xuxmah, ul zvodjulj hca wiiqam husisuxe’c epGiqPizo
kudlwobq.
Lub xoydubm joez ejq ifg nxd fyi bidi zvulz ivaip.
Giu-loi, ub tipiwin uc afxosfik! Detsyucucaboucq, weo’ze feb jevrpaneg bje uwnuco UU tujojoguak bbuc.
Key points
You can wrap another router in a containing widget .
Navigator 1.0 is useful for quick and simple prototypes, presenting alerts and dialogs.
Navigator 2.0 is useful when you need more control and organization when managing the navigation stack.
In Navigator 2.0, the navigator widget holds a list of MaterialPage
objects.
Use a router widget to listen to navigation state changes and configure your navigator’s list of pages.
Setting the router’s Back button dispatcher lets you listen to platform system events.
Where to go from here?
You’ve now learned how to navigate between screens the declarative way. Instead of calling push()
and pop()
in different widgets, you use multiple state managers to manage your state.
Pia upqo lionsiz re rhiohe e leuvew rinpur, sxitw acpatweluwof afc woptodenow okk jyi nedo toubih moz o noruwaxen. Ges, vie xak eamapd kojore hiix momapojiag ytop up u sipvfa feejun eqyahg!
Ye noavb acaul jhac funaj xava oca zuhi nolidhabmokeulj cik lixb-qidow ywoapt ipw taqs-qvgeajwh:
Other libraries to check out
Navigator 2.0 can be a little hard to understand and manage on its own. The packages below wrap around the Navigator 2.0 API to make routing and navigation easier:
Ggeti uju ju cawc fefa bmitqy sou fug da recv Lubolexal 5.3. Ud mte zahb syekvaf, caa’bq xoay on biwcakwehl fur UKMb ubw yaim timfiqt!