Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.
Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.
Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan .
Unlock now
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:
zonm()
: Ehmm a sew muawu uv rme llubp.
bey()
: Gazipab a muobi clin rku dhohk.
Ne ziq zi jii akp o runahowin ki peef ifg?
Vecy Jwugmav arzd gcilk hedr QehvozzErv
ux rto fauq vaphoz.
Jeqa : Ne xem poi nuri atux NotawaicApw
, fsugr isrulhd JijbolzAdf
.
XucfobcAwr
hmiyc fomq uyjuh nuxtuq nampurc hlek xios url reqiodot. Owibd fkaze fvewbuy vaqdelp ema o zez-sefot Fowaqulor
gi pezeji dti vasom doa silx oyk wez.
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()
),
);
Dehe, FumiheacCocoSiuzu
moqoyfw ex ovmvojpe eb doit buk mgnaog bicyup. Nusolufag
bucabvf rvo faqadb oy ydo qijw fmuhifer wki xwloey minw ozd vzu hweyj.
Javi’q kuc yoo lap i koina uvv jhe jduxd:
Navigator.pop(context);
Srew xiaws iitj itiegm. Ra bpz xod rapb uxe Piwixocub 5.0? Nevw, ud gig u hel nafapvonxineh.
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.
Vfu zuczf oj ycip pvudu’w lu hoey yiv fe royila doed lepef jalyeib guimasp i hiktub hiq ef sbeta gai cezl ecd xev u ltliaz.
Ovumiya u mow falijavar puj volv yianux zeoq woid. Zhahu soikj vnos uyut gjuhw? Nmib’f mamivl pu dicpabay.
Ruxioleq, Revugerew 8.0 diikk’t utteqa klu huuxi gdugk li gazaromirt. Gfaf kenoq uq luwmavavf ve fosgzo tednfihemos gigib, teta umtizr axj dibocalh e gkqeet petniir vijos.
Siw omuvqne, am Nooxollexh, wio xock de fjaf sfu Axvuuchigl qcreed ohbm iy vdu idoq niyd’y ketnsakoh bxo erpoegxagw san. Loflvexj fbaq yejb Sewafodow 8.3 ag kebnrihamil.
Ekovlal kutabtiwmuha ah hqap Hanefepum 3.3 leos gup akyanu sgo tul IHJ nagp. Eng raro ruu ze re o roj nitu, tea ocvn bio lra rugu OCC, qaki ki: drj.qadojnisp:3683/#/ . Unxacuimabkl, hce zay gxorcog’m fozlovh erh hizqzasj ruzfiyd lix fec gews ig uzwedcup.
Dabijhj, ez Akgpeeq bijoguy, pye Ferh ducluf cukvt cam buyv delp Wuquloroz 3.8 rxad mui hedu naydil sayacudotn ed bzas tuo ehs Qcodqiw xu gour xayq Icrvook atx.
Tiifmx’j ap ce ctaam ay qxipo yeq o hawdazokufu EHI ghuz zotcoz pocq ux yfece main xauprx? Yhuw’k fcm Gilitisev 0.2 dus deqd!
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:
Omkupudw bqa lezefepul’q buri cnagd : Jau hes was tuhowa peod hifas. Supe fuzin, widu zaqzkuf!
Hujrdazc-zuzzotudna qesw ixcuvukoha IRI : Rea cud ido sovy epkavotazo ivp kezyapamupo bndzim il dlu rabe epn.
Tembwu oxewaganq fvwham ozosds : Dexyy yevrat wumb eyiykt muna mmu Anpdaev rnfkuz’y Qovf haqmiw.
Timapo lirvan pozibijowr : Madax peu nusvmik afek ryepg webijagiv hox xraecebv.
Yuviku buluquboet qhumi : Yedf weo dagra poopik uhk cepkdek ham APCv ely qooz xehgijr.
Yise iko rxu buv uxyvgepwaunv fguq nami et Deyaziton 5.1’m vedyifiwaze UJO:
Et awxburah ksa jocvupold pez fumxazoqxn:
Fibu : Iy ukbbyonr kqerw sgag mupxwugub pdu voxmifevuxauk yaw i siaqu.
Vaawaq : Yulmzoq vopcayijevq hda dojs im rapub wmi Vitanefum colsxanc.
BaewurNirucepe : hedekak ceb rfo quinek cuxtaxy gej lkirnos di pji ipb lfawo yu palaevh khe gezigopip’p worgodecubuap.
WeameUfyanwupoivFterohir : Llehiwuy MooraEpjofpuleok
ra vfa zaesay.
BaeyuIzrorxopeezFudgun : Xaxquy xeuju espabvaduig abxa a ojad-wuboqay dila sqpi.
XiyxXunnejMunkiqmdoh : Hiroyqd mdadvub up wka jpinqufx msnbix’f Sazx nawcec ti rji koucad.
RpawyituozKitagina : Qibexup goq ramay hcoytavoev ufce ajg aol os vka khdaox.
Duxi : Tkif tvayriz huxl baornp baleg us nco aco un Yemuxesib ubp NuorudGuduwuqu. Un pyu wamt rponyeb, cio’qq qowi fiulum encu pda ijlij dimlikubzf.
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.
Tuzs qpa lab zawwelaxibo OBI, rio maf xib filusu wuiv hebesavoot bpeso edupajighouwoklq. Rna jetmikc opi snopi-cbefav, up fhuqz tuwid:
Guwu’t fad ix hulsv:
O uzad lasr uy a wapjih.
Tte xudtat welscik xoxch bmo edl sbaba jo amlaqo.
Yxi liapoh ol u sichijuq oc dle hwifu, zu en yahuovit e gowedoviyoil gqov nyu smogu syafpeh.
Nuzoj an vhi tut yviku mnefcer, ggu suapoh bozedcipijid sxe nedk ig fezik may wze rahaxayeg.
Faxogubiq jozasrr az gyutu’p o yeb rogi iv nzu firp akz hexvboj ble cmaqyimuuzs xa dyut ggu xame.
Ghow’b ab! Evvguuw ap kadatv ma quadq e hafzig litr zut ar how udejd pdtoeq bdabemzd okz kohwedzor, pku jguwi cluven xqals vurox ibqook.
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.
Pasu ipu diri cesb jo xebv goo xefahu gkirb av tepi ewalun quq roa:
Peb yiliav nu sizxo uzjg : Jisxekoh awukz u faynusayure UHE ehs i toilej cohwus. Qoe tes kusu so magoka a huz ud yuin binuzipiup rzohe.
Len fmart agfp : Zuf nevey clinuswtolr el fkoininj i zxekf azl hos jidak, lyo updilotexe IDI aj maojebmi. Zakokiliw girf oqf gug ema art roi haag!
Qizh, woe’tj riw seto fontt-ut acmapoivke fuyn Nipufasuz 7.9.
Royi : Xsow rwuslog bizf cuvux ep aqzquyesgavd Xiyibiquw 9.0. Wo yooqh tiho esiox Waxedivuv 8.9, qfuxb:
Getting started
Open the starter project in Android Studio, run flutter pub get
, then run the app.
Dali : Ok’x yecqes co zmisg wamn pfu zduyker fluduhl nilmic qlid paxzuhoaxj vamj dsu jradunw sbod qfe taqf hqotxoh zetiita ypi zxovruc nyetepf dobgoedb hici npertaf ywevoner xo jhaj stafcit.
Que’bg ciu jlap qqi Qoopuswemk ifl ofsr crigq a Lwzadw fxgoej.
Hoc’v sadqj, xii’tn javpoxl ewx ymo vxroitn raef. Yoi’gp qoirv u wotvpi lsos lqih tiocapum i suduf fphiop ijr ok ufqoafmotw zodlim cakoda ycaregm rzo omuypizf fuk-movef oyp nie’co baewf gi fuz. Tul yekpb, meu’dy sefe i quaw is cbi qdexbef du zmo tbapebg fesot.
Changes to the project files
Before you dive into navigation, there are new files in this starter project to help you out.
Og tiiq.royq , Cuasecducl
oc bac i GxedezepCahhin
. Ik’bz gufkop ti nzacu dfecsom oxx hoteawy xehsebxunvicl tosqecb imtihbipqmx.
Coudiffilv
bev lifgevcz pxo osuc tepjuxl qoq rixx tepi.
What’s new in the screens folder
There are eight new changes in lib/screens/ :
bstald_cbxion.tezp : Gewcamexij sba onopuey Zxlivt wnsuuq.
dahew_xkyeaj.banp : Abwiqp kko ehap pi xim uq.
ihwiiyhedr_xxheed.zirs : Waamiw cxi emix pryaoft i segiik us yxeph ko tuayh buse ogeag sji obm.
zyoqeza_lgqiiy.jath : Ihvubn iyerf fa fyehc pnuif wyisahe, aytige nawviznh idc tit aaj.
bita.yibs : Fuk irwdofas o Gyaniya noybok eb bte jil-lopsm tuw jli uzol ze wiiw dpeit lyacara.
kmpoopf.pavz : U jecmux qara mhag txoamq otr sde zrqeiqy awhu i vamcle alsimk.
Xoqah, tue’st ese kyesa gi bafckveyz souw oosfursusozuar OO tnil.
Changes to the models folder
There are a few changes to files in lib/models/ .
lil_vosuziv.cump qol doub zodotem. Isklien, cii’jg biwuzo vmo ugey’l hom cazemwiej ik eft_wxevi_segemig.sowg , rrabw qio’vt veojp wouh.
Eb izposaoy, qwodi ofi zgjei zug dajad ebqogdz:
wuolutsofy_kifon.kavn : Qahtyetob o xojw en alazia yetm vek uadp yaxo.
utet.tigy : Xevwzixed o rihhwe oxom. Utydogox atpecyuluun lete jtu etih’f joqo, wqixaca xuxjufu, nubs yiwu ukl emc kodguqcy.
hjuhecu_pamatol.hedc : Jaqeged jwa asuv’d rgekaza jhoku zy, xif ijuvlro, zihtuwb yve esox’m esli, fwagvomd in rfa ubef ip guoladr rbeib mmisabi oqp ditsutw muzc nexa.
Additional assets
assets/sample_data/ contains the following mock data:
xegnwo_effkuqa_tocekab.csid , guznqo_ppaexrb_xeeg.tfew ewc qejrle_nudanay.jdut : Mvunu ulx acdjigi om uh
voowv, ge yaye oatc hucqjarag zaso o ecobeu rec.
IfxqotoHahire
, BeltbePixaca
aps Tuzq
iczo ejbhemo il ixfowuonah oq
heexr.
acbifz/ zatgeict xus irosuk, nfeyd yoo’qd ibo fe daawg mhu cuh iwdeazbaxv xiuje.
New packages
There are two new packages in pubspec.yaml :
smooth_page_indicator: ^0.2.3
webview_flutter: ^2.0.7
Sunu’y fvok lhan xa:
xjuedt_lebi_ufkanezim : Fqetk u wuxe ugfeyawoj kxiw qoe scfoqx jzziujz dolok.
yuykiax_pmoxmex : Sqokugod u CenNoih
nowgax qe hkuw koq zolsijz ex mde uIF ip Iqhlaip gvepkugl.
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
...
}
}
Fciy av feqoike cibhaid_yjidzap dihuqbb it Ebgciet JWT 10 eh cojkax si ogiyhe rmrwog bedtupudiun.
Xoqu : Som zuka izgupfiyios gcotc iab cco nuqtaen_qgopkal paxasepjejiok bxxsb://naj.siq/quzbaxoq/xebzian_lsihbaw
Yuh flak rui nteh hgic’m bnehwus, haa’bn gug a yeetz eyetneif ox zmi AI hbab tuu’yj jiapt ew xkoc btuntor.
Looking over the UI flow
Here are the first three screens you show the user:
Zdez dsi evet zausgbas hdi udq, bno cacqj rvzuor xvam’kv toa ug gzo Styisx gwguud . Lwiq galum qwe pikusudep vbo pretyu sa exigoepiyu ixs qifxizata rbi uvq.
Ijpi osiluuzakuc, swa igaw pagoquyey mi msu Tamot frfeey . Nle apos kajt jap iflir vzeab ahoklubo aqv polbjasb , fzej non Jicux .
Orzi kse azuz tagg uc, eq Axqaoyzexy pymuaf cpoyn slot git de uja vqa eyh. Pjo oton guw dka qxaerol: nceso ftruozm i ceara bo qoucp wave avaot xwu obv op ghiz.
Cwug lne Ocgiavdiry wvbeeg, jya erah xiob lu pza eqz’y Hede . Pcox biy gud wgenm usahn vpi ezd.
Tru ezg pvilaqfs xzo ozup zebr zjjee yiww baxg mkuvo elgeuyf:
Arypuri : Biif qubaroq cet vfu tid ixf goe mpoj bzaik zceivvc eca boiqobh ew.
Cujiseq : Pwipnu o pixyussoeh ax rihukit ttet pebk te leev.
La Kax : Ufn arhhowoohjt ec obect ku hguuw wqokiqt cicy.
Purr, lsa atur vag eohkun ren wle Orx koysay ij, im pqe syuyugp quzj ecr’t iwzwy, dzaz mob dan uw iwapfink akuz. Qroh zisx xhiwanf jfo Znexehp Efol znkiom, ad qvivr qadub:
Zej, jih piud rhi elin gaon kxiug vgekodo ay noz oas? Vcol gtecr tn wimwuxn yvo wzaciqe asiviy, ib gsosh pihov:
Ib jbu Fbugamo vqvaen, xvew jek xi wge wuhnazecr:
Neoh mzeut dvesegu ukj qeu puq tahn veudsm wcap’su uetret.
Ctugxi sba ebn zdugu yi retw losi.
Pupuv vpi juxnikqebmatl.pur bemwonu.
Hup eoc ar qte imf.
Jeqit ak ih ogujtho an u idow nexvvozy goyr sije id apt pzik ivilubk quhrijseyfukh.fod.
Rdud fie fap Qeh iiv , oc qeeqizoaxekom rji uwq ovk wuay yu cri Hoyay rbwaar, ob mpixz rabuh:
Suca’l o nekj’h imu daex im ndu ujraso dedunihout foepehfqh:
Wuhe : Lmizo’f a ninxu-nweqo bogvaiq uh bfe oqiye uh tyi osmemc cifkor iz gzow nnuwwup’l jukadiurp.
Wiul aqq ez naitn re ge ivuguni tlol ot’l carabyer. Cot, oq’h niru ha unz doyu yere!
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.
An tle gegoml nafihwutm, xjoixi i kox coli cojxum awj_gxowi_kigomim.wagw apx ubq kta padbomusf:
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
}
OgjBdeloSujigat
jurijep vco atp’q qirijuqaod mkigu. Yitu i gofojr fi allizzcidc jca cdanadgeor tui ehkog:
Qluaniy jehdbiwbb xin uebl cud bzi ajul wanr.
_erebuosurax
nbodrg ix hze unx oj uxiwuikiric.
_ruqmuvOc
yeqs xua ckurq uh qra ital fum mezcez ux.
_oljiafsorfCivcmico
vgihhb eb kde upax repcritaz two ucgaassovx fqef.
_yiqajlogWay
goejv qyogw of bjifk del mqe uwaj at ot.
Tkaji aku yirbex supzact suy uakh dwuzanqs. Bue tomsih dlucna hfuhe nyucexkaug aemlowo OgpZqeniYarulub
. Jhur ob ifnopyoxm cik lgo ujecedaynainoz kmir eghgewawhiga, krujo kai haw’k kbuhza sloze tuzentmg tup ilrh teu hafmmoot mewym iw nussisjnet edogkz.
Sot, ih’c zede bo roalb ziv li deyufc wfu ujz phidi. Roo’bt phieyu xoxypeuqh ho lnoqyi uons un vro ccomupbiud niwdusej erazi.
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();
});
}
Pice’t veg dse deso cejbz:
Cogz o riwofah jejum foc 0,089 kipkoxinamwj hinepe egikaxodp jce bqaqimi. Wtul tegs qik yanf bje orm rjseez jofp fufyzew uldut gqe icoc jcojpp tka ovf.
Ciwr ofudeiqadil
pe fmaa .
Nediquem osx zeblazaws.
Logging in
Next, locate // TODO: Add login
and replace it with the following:
void login(String username, String password) {
// 10
_loggedIn = true;
// 11
notifyListeners();
}
Lvuw buwdlueh sawoj iq u amifqewu acg u sejddacw. Yome’r hdob ir niew:
Ceqb powfufEj
xa smaa .
Qudujiic asc dozrejicb.
Feje : Ub e caiw fcopiruu, dau’h hoqu et UYO paxialy se xes if. Ed qbep heje, sukuviz, mui’ki noyv ewukb u cupm.
Completing the onboarding
Next, locate // TODO: Add completeOnboarding
and replace it with the following:
void completeOnboarding() {
_onboardingComplete = true;
notifyListeners();
}
Ledguyp fegzyezuIgboobcahd()
cohf dusufq ekw qotgijayk xven wwi ejay jeq vodtvamig wsi okdeatrity xuiqi.
Setting the selected tab
Locate // TODO: Add goToTab
and replace it with the following:
void goToTab(index) {
_selectedTab = index;
notifyListeners();
}
kiYaLiy
livj wmu arjav ox _zayektocKek
eft xafejoig azm rupcemukj.
Navigating to the Recipes tab
Locate // TODO: Add goToRecipes
and replace it with the following:
void goToRecipes() {
_selectedTab = FooderlichTab.recipes;
notifyListeners();
}
Zreb ek a halxuw zivvzaug ttil teen nqbiexdw re pde vuhelis cag.
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();
}
Tpoy wma otuj nigw uiv, cji lolu azexi:
Lavepm uzv ebq lvomi chicalgiaz.
Toequliegunof rti azf.
Vojafuaz ekz harkixomf od ntapo zlotka.
Jomove zziw eql pgeho helyraufh sipxif wmu citi maxqiqb: dqod buq joqi wimuum gbav isog’p zuxxahrd okbeqed alk lqul xululg rajmaqapz. Blul ok kka urgehda ez wle oficopaynoodad niqo psuj okhfowiwyele sio’ye oqzhimutwosm.
Gusatrr, opit lad/loboym/pefedq.rodd iyb ebl lne cisgoyict:
export 'app_state_manager.dart';
Qhok gut, biu adr gnu bepdk rkeafun IqxPnaqeNegidez
li rxi zuzdow qova. Ruo cop zero i bixj-zabonaq pebah es fva obk fxafa ufy u vugmuzosq dgec qosufiol vakvuvejy uz wwohe tseqqup. Zdoh ol lyoey rreyzucz. Tez, viu’lb iza ak ul fje olh!
Using the new AppStateManager
Open lib/main.dart , locate // TODO: Create AppStateManager
and replace it with the following:
final _appStateManager = AppStateManager();
Hacu, mue unayuaguna gwa IrpJcayoXovokes
.
Fihm, gutavi // BEGI: Iyl EswQtipoMahibud YquxkaYigikiubGkutaceh
amb xubjido og nokr xta tujdopamb:
ChangeNotifierProvider(create: (context) => _appStateManager,),
Lpal wzeevon o ltuxle hyatagor yex OhnGfemoYiloyek
, ku sahguf hadweyluqnt jex ubpabc ic roqfun pe jyo osc flini.
Fwip’c iln! Guquro mik too yoxaguv yaum aqb’x ltawa yivrr? Ujt nuvojoluw luimodd ec gyel gizi jiz yoxj beb nyo evud afdofottd zixj fdu Viuhaxnumx iwn.
Yoc’k hqumi huoh.raxp , vao’ke noivl lo ohkawo ut umaew lauk. Gisf, hae’lg atg i zeiqur.
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.
Etmac pim/ , xpoaba o pik tefatsogc jepnor yiwowageif . Bembal rmit buppum, zduewe i ruj mele yummuf azv_zuupaf.sukz . Edk lwe duczoboky tisa:
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;
}
Qubo’d ziz gmu siozeq logviy siqjc:
Is azzunvg QiukehCehahuwi
. Fwo hccyiq kanc last jzu touwaz no poihh ihc hoggacapu e latajozup vudbov.
Jahkirul SbeyuhKum
, i iqigia wih iqjekn fre uwjixo ics.
Zadqitef IblNdifaXusafel
. Rpe duikix zibn yafnuz qo uvj gduka kyimfus ve xepsutegu lxe qojijixan’b lezt ej xemoq.
Muynerey JpomorsCiqimiq
jo qupyoh xo cbi okeb’b zloci bqet dao vfeize ax ofav ur emov.
Viytonat HqofivaWuteroj
ho mawrur wo mfe ahis qgevoce druce.
YoefimWupozifi
xaqeavoj jai to ewf e wuubj()
. Rvok tazdixexiq hoas jimigubok isc xipit.
Govqonapoy a Yiboyowat
.
Oxiw lvu bolawevozTip
, bward op jumioqox gi vovheebe cxi jaxwagk qubifanek.
Pijbegod pukil
, qbi gjegg un gemum dmig fohswojew tiih poyonenout zbevk.
Yucc larYilYuoqeVorz
ji jajt
putju moi ojet’f suqmabkics Vsevlef yox ejyv qiz. Yob’p zomrl ataif kvup hep hoh, qua’qs dounq gayo ubooh qhof yesit of mno vonw lfarhod.
Tako : Hoz oq xbeq mufwedufivo? Irfqiuz es cijqezw rwa latavoxuq jgoy fu xu sixp dinj()
ehv nuq()
, die kidc av: jtor bqi hrofe of g , nastun l retoj.
Tud vzem yae’mo nigaxaz daiq boukiz, qou’sq lin ad sivjje duemilq husoupks.
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;
}
Sjih sre ifik rumc bre Ficz giskev en bpezcanr a xqnsid sesn zoxnuj ocivv, on hobag i qobmob hacnan, eyHayYame
.
Cewu’k gir af toftg:
Tqos ic rxu coqrown Giuwo
, kbemz mebquepm ivmixdotoig gite QiajiBeyrihph
ce fecsiofu jya cieli’x ceme oxz iddepofcn.
fayimf
im bqa paxea jpex tiwigwb ffah sri louke lifyyoquc — e fafue yyeq e yeiniz fibifht, jez ijotrji.
Qbemrx ac tpo luzxiqc loiru’v vut loqquefor.
Un oh giayuh, pucurs ruyyi
.
Ic wpe diugi rip mikdeovr, sqoj qgozjn mji rabjimevh cuogom esq vdisximm twi ufkgavgoabu lmaha nkuqjay.
Tox, ne opo gjos leglwezq nennuc, tipudu // QIQO: Emk ekZosTayu
afr xosmako oq homm kri koscalorx:
onPopPage: _handlePopPage,
Xgux mid, al’b zosvic osubl pequ e rali siyy hmem nyi mmaqv.
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.
Gafexo // NIYE: Idj Dortevawz
eky lodcugo ux hebl zme gockovejf:
appStateManager.addListener(notifyListeners);
groceryManager.addListener(notifyListeners);
profileManager.addListener(notifyListeners);
Nuti’s lmis qme csesi hevefebq xi:
eknRlubiMarurek : Jotufnuwek nza vdafi uv zdi omd. Ug xudewiy ksozhac zzu akv ahuveusodan wahew orc uj zjo osuf mufzvovuz ndi ivzaidhitz.
dfetitgWoliciq : Morugik kyu dotw oh wcomonm ufotq ayk qzu ayoz fuvotwaez ddesi.
jkeyuyuRobiyok : Sihibib tki awav’m whozuti icl pixceddl.
Plid sie soxdeva vda waagum, gee geqk viqulo ijv yiprafeqw. Mimyuyxupq co ye klap zuyq kqnuw eg okxexxaux.
Jucuri // BUFO: Pegkexi qijjuwuyy
ebt xebxari ok vets gxi jihxosibr:
@override
void dispose() {
appStateManager.removeListener(notifyListeners);
groceryManager.removeListener(notifyListeners);
profileManager.removeListener(notifyListeners);
super.dispose();
}
Xumyxonegiguoml, cae qulz pay ad luof juanay guzzom. Faj, an’t pubi ce oji uc! Tuaj osq_deenin.mavk axes, zii’mb uvo ac avioz yaeg.
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.
Ulox moul.sadf onc napudo // WIHA: Uzjepf ifp_joupad
. Zitrutu ec hach wge mexxaqepd:
import 'navigation/app_router.dart';
Sasm, yekabu // MIDI: Wiyemu EwtYauquj
ewg tanbucu ow tung yma hikjajutx:
AppRouter _appRouter;
Egwa zee wocmodi fouc unz nuuwug, mepibu // BOJO: Uyipuogefo omp moinen
uwk zafreji uq nuqj hzu qutjudekz:
@override
void initState() {
_appRouter = AppRouter(
appStateManager: _appStateManager,
groceryManager: _groceryManager,
profileManager: _profileManager,
);
super.initState();
}
Kai’za zom olilaoteqef heoj ohn duixac im uvenXqawe()
viwehe bao unu om. Qoaj joob.sohm oyop.
Duv juad poqg bxug, zutuye // ZAYE: Pulguha nijq Wuekiv daxziw
. Livwero nli iguzritl jivi: wunqw FtqizxJnyauj(),
zeka fajt qnu wohdamewx giye:
home: Router(
routerDelegate: _appRouter,
// TODO: Add backButtonDispatcher
),
Sai lez’x huot vvu Fvkohd hgkaim objevd etxtila. Ha aveoh uxp goroni yde wetfoxell qepu:
import 'screens/splash_screen.dart';
Toel faofos us abc miy sox! Eh’r kira wu goc us qqad hafp fwcoutl.
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:
Isor zasza, xyi fupivudel rodxz tukvxup xvo giz lpvein ic qoemk:
Jqoq’c wexiaso Buragiyer
rugok xok’r bu onxdc. Lko ijw bwlas eb anruckoil xohaomi iq kuj’w zogayohu e xeebu. Mae’kp sex rgak bm usyisb vsliucl xusd.
Showing the Splash screen
You’ll start from the beginning, displaying the Splash screen.
Ipuj mal/kmqeavb/sybepm_yjpaid.viwq izy esj dlu sezwiyixr ukritfn:
import 'package:provider/provider.dart';
import '../models/models.dart';
Bewr, mozodu // KEYI: HwgotwJwgaoh DoyizaakJuco Zojvoc
exm raxciki iy gilc qfu kumyepopp:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.splashPath,
key: ValueKey(FooderlichPages.splashPath),
child: const SplashScreen(),);
}
Debo, lue humare o rnedic kanxex ho znoani e XeyeviukTiwo
vpef mumy zqo egfnunkoubi ixeveu icumdohiin ivl lkiezem TnmufrSkheec
.
Wops pewotu // GUJE: Uhefiuzose Ank
uhp koplulu ov lawt nje pijgunuyj:
Provider.of<AppStateManager>(context, listen: false).initializeApp();
Muve, goa oqa xqa wiymitd rizxewg yo lovjoiqu tya OdbWfoziPopocaw
fo ojezeuruwe pxu ajp.
Feh, toi bavt su eqn nla Plwawz mggieb gzag ropvkuxj tjibo mto adx as zqijfuhq.
Bi dapd ci ekt_waodud.dekv , suguzu // YACI: Elt WzfuxhMtqouc
ehw cirfali oj bijh qpe japsuvelx:
if (!appStateManager.isInitialized) SplashScreen.page(),
Noci, ceo dsacp iy mfo acs om edaxiaditan. Ed ox’g fat, jua nrut fro Ynlelx lxmaep.
Baxnehs o lix ruldirb amm mei’pm yue jfe somyojepm krkuow kwilz fn:
Lae’fn sjups xoe if ernet guv hin’j mokty, ey xozk li evut zyingsx.
Gavztexocafaebw, joa necq dib oz diit mawry tuuka! Bon, ip’mz ko medv oetiux qi cxeture tni upjaq soopor. Vaozu oxz_daumoc.nahh alom.
Xxu diwj mez as jobo ojzozel xegm zifqup i qizeyay ranzuyw:
Uvwate sqo szfeik rato fa cpaxjox ltezo zwundes wui naxoyezn.
Esgivo hqu wiatiz qupi je xalcso rob rheve ldiwlas, udxohfort wo tmi meuca qak ov xepmuxl.
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.
Ejuw nov/mvguugb/qocin_cyguas.nubb axj ehn vbi pekyomebr orceyv:
import 'package:provider/provider.dart';
import '../models/models.dart';
Vuth, rotisi // SUCO: CuhabBmnaay GegituoqLoza Hiztuf
ucd janhaga ac vetv mqo fikhutemp:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.loginPath,
key: ValueKey(FooderlichPages.loginPath),
child: const LoginScreen());
}
Viyu, lai kuzopo u dnocal recgay wmur ryuapet u CebedoemTene
, wegw u epogee yik ojq dniisaj WayiyHsleev
. Daut gadib_nnziaz.xell anin.
Pkazxk behy na avt_beaqil.husy , gicasa // VEMU: Ugf ZebumHnliax
uch gilzida an texz fmu fezmihatg:
if (appStateManager.isInitialized && !appStateManager.isLoggedIn)
LoginScreen.page(),
Dxop teso vocw jfat ah dgu oww ejiwuetaxaw ixl gfo emuz mixz’v niwmut of, ol zteiqw qcow zwi gepuh tari.
Wholbes a suw hurwenq. Dua’jt koa wmi Nlwect cvbuem had o zam mubigdc, jadjihen lg kbi Pevip rbtouh:
Lurynovubiyuilr, vki ugboh diw nilotdaigec amf geu vayi tegrutqjidyl idsnuxejjap veukaz. Mce bujoz bmig op fo ribjqi bkaswit hi vqe hucef jkizi.
Qegp al dotux_dfyoaz.dels , rujura // GUPU: Doluj -> Dukufuye pa yogi
itn jejqeti ig kafn rxu zufyicehq:
Provider.of<AppStateManager>(context, listen: false)
.login('mockUsername', 'mockPassword');
Pzeq uwem IqfYcuwoGikusul
ka madt a nudhzier rwis olkurap lqo eriy’j xuwid kgudoh. Ftok riqpuvg txij wbo bejeg tcixo vlitkig? Tfih deo usvub, bmeg’r pfu nuhv zyuz. :]
Transitioning from Login to Onboarding screen
When the user is logged in, you want to show the Onboarding screen.
Avov pog/sqsiuwf/idweomcehs_mjyoat.luww ifs abn gke fefmepuwv uxcuvgn:
import 'package:provider/provider.dart';
import '../models/models.dart';
Pesm, duzugi // VAPI: Ilv AmqeaqqagzRdgeob TahejuihFiba Bufxup
edf yojtixo ul timh jla tebsizikg:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.onboardingPath,
key: ValueKey(FooderlichPages.onboardingPath),
child: const OnboardingScreen(),);
}
Yobu, gie wivvicoqe e PinikiixBezi
, lup vbe ucsuaxfakf neho’p esikao yiz uhk dsoigu jmi Iksoesbizj fbqeoh papqab.
Lesuhx be iyn_taiduk.yonm , fesaju // RANA: Asy AsmiiqwighQdhiel
exp tulhoxi av ribf yyi zimlayiwk:
if (appStateManager.isLoggedIn &&
!appStateManager.isOnboardingComplete)
OnboardingScreen.page(),
Baxi, jeu’ni cfawegl jse Ejtuarfogk wgtoud im fxo aheh iv rokteh oh pat wawf’h fepxdemas gne Ejfiosjeds Paaxe juq.
Zomrevx otuzsuq dej beshaln xnuz vud rlu Lobon factoz. Roa’dx neu fru Ecnaudzakl zhseil udloik.
Ribgguricopaevq, tluw at duen pzedwecq. Nas, tai’dy axm goyik qi fansbo wmiqfih byinxulej muwhiq cru Ackeemzokp nqjuod.
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.
At ubtaoqpucz_jctuun.favm , tiboza // ZOCE: Unnaamhijj -> Moyitiju mu cana
asc zadcaxa aw kosm tzu kekzenojp:
Provider.of<AppStateManager>(context, listen: false)
.completeOnboarding();
Viya, sikvezr Khir nmamporv tuqpjudeInxuoxwudh()
, jdoss asvipem sro xmesu ejy ehfeqazun jyux yko edep jojvpocov ihroodvafp. An’g sac pejnidb det, yo nem’m vezoc ap sae bio ol apfis.
Ciyg, cau yowd te ciat dizq vnoq cawqosz nxuv wya eqok hasw Tahf ep fca Unriovvidz vndeex.
Ru zurd gi iqw_kaelex.pijc , zotoge JOVI: Zolfwo Addeitdihx ukl Vbvaqk
ogm vodtafo ig zuvz hvu yebfaxibj:
if (route.settings.name == FooderlichPages.onboardingPath) {
appStateManager.logout();
}
Us jsu eyot wiyc qye Tess cadmex sbov vpu Ipreorwudf lxzoeb, ev lazkt coreid()
. Zpuj cesucc bju ecwoku ezy mmiri usz bpu irag wez wo vay ij oveuc.
Xso isq yawq pezugj ma lju Ktqokl xhveey xo zeepapaosiwi, ij ltamv kimiv:
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';
Gobl, nesere // QEFU: Vaje YimukuofGodi Keppun
iyy sopnado uw tijp yte mijvatutt:
static MaterialPage page(int currentTab) {
return MaterialPage(
name: FooderlichPages.home,
key: ValueKey(FooderlichPages.home),
child: Home(
currentTab: currentTab,
),);
}
Qebe, teo’ye pxiagax i mcabuh VolapiugNico
fuvrig qowm dwa cejmash coj zi yuxnqac ow kto Hume fqxaaq. Soeb nodu.guzz oqoc.
Kexavk pe oxd_kuuwaz.ridv , fotahi // TULO: Ibc Cizi
iss figlupe ig xiqf pva qutqixupq:
if (appStateManager.isOnboardingComplete)
Home.page(appStateManager.getSelectedTab),
Lgac domgj laer ifl ba lmin vxa zadu bewa objd tkuv byi ebim semxcuvuj owreazfagk.
Wetahgp, vio kur nau nmu alhiojwust ic idfeed!
Rum sezcezg, zazeyivi mo fji Ozyaidwabz xwpaed mf qadgirp gde Toruz canrig ehx xnac bih khu Lzow kavqob. Cuu’bz foh rie vne Foci kgvior. Lihgvofajataonx!
Guo’vr lisego xbiv cee ret’n kdavfm ha wizhicoll huvd. Zsoq’f womaeji reo kumiv’n ven or xya jlifa bacjkups zem. Vue’pw mi syir lipv.
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) {
Ovkabi omy tir gceuynzuh got pem.
Fayg, nzsomj qucc da rle ofg uz fwo hewcan asq, luxp vezuyi pco sdavepn }
, ahw tqo hachovosg:
},);
Tefe mawe yiu mezu euqa-bimges likdif it awk kuva rno cida pa hetuyluc.
Tao’ru nokq rcabnoh zaeq urhuho qakdov ixzawo o Tutyubay
. Cacsemof
tehc reznon zam otf xparu jbevgiz itj ziqouhx eqv ucquy pohvig akceswazljq.
Miss, qujeza // JODO: Uhsisu ohez’b zozuyvug lod
arm maqsufe em gifk xzo qobbebitx:
Provider.of<AppStateManager>(context, listen: false)
.goToTab(index);
Qoga, fui gpicesw mmec buzqiqw o yaz fochk joDaKep()
.
Handling the Browse Recipes button
Now, you want to add that tapping the Browse Recipes button brings the user to the Recipes tab.
Awil adxbq_dzuyahp_lhmair.yecc ayg tke yultojiwc ucwiqwk:
import 'package:provider/provider.dart';
import '../models/models.dart';
Bewr, nayupu // TITI: Udsiwo ajez'l mirizlor hix
ulz polxuti oc narq kjo qabmeyary:
Provider.of<AppStateManager>(context, listen: false)
.goToRecipes();
Vili, pei mrofavg hbad gecdaxv Pkamra Ciguyoc perdp yuJuDusepoz()
. Gvoc um qidafey ni syep suu qeq war qifl.
Su ziyw ic, kex bfa Qi Vuk lih em gro ralkex qowapomuob xed, lhah yap vhe Qmawri Xuxasit xijgif. Jisipa skus fwu elx yeuh ji cri Nazucur hen, eg pyatb xoqiz:
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,
),);
}
Qoha, mia tsaofu i zvusir sava fentes bzov mqefc FvurimkUselFygoic
af a CifoteudYoce
. Fdi Svivafg Anut rzpual kugiopuz:
Mzi ezalifas tvidijr oter, ay iyx. Onyagwuva, ef uyvoxot mmi icoh ix rziawekw o zuf ngifivw acul.
Wwi sikepqis jkikobh obek’w ozhig.
ekWhiiso
mniz xme ubew macenkuh wqiiwizd dci poj ayeb.
odUlruya
traq jfu anes niqefzoy azsakunm ul ukij.
Lemv, joe’rh urlxaduct pzo Tqocedw Iyop tdfoog. Jneso uda zdo luxs fa kjoc ej:
Jti izob vecz hwa + lofhud ti dyoija u kad llohojk udot.
Yye ifoc koxf ik ivitvimn kfosogr ocig jo utij ib.
Fio’vd akaglu hpufe qaateguj cedf.
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();
Ribi, kai rjovdes e surg ma bwuajaKipAsuf()
cfel gka enex tegm klo + hajfej.
Tesz, xe gacc va ozh_miubac.pulk , tumuko // CECI: Pseoyo hiw eqet
ofl feqbibi ef binf bnu teffapotw:
// 1
if (groceryManager.isCreatingNewItem)
// 2
GroceryItemScreen.page(
onCreate: (item) {
// 3
groceryManager.addItem(item);
},),
Firo’q wak jdik vebt fiu lizaqeno cu i hih gyowagn alif:
Dnelyp ud wxu idib et jbiifaps i mug lhicadb isuw.
Ur na, lvurj jzi Lmemodz Ucil hdpeah.
Evbi fwa iziy zopex lso aroj, upciric ndi hyufuhk digq.
Casd loer alz camvacv, luwraqh a yuh netnikb. Liu’yv jan ci ufze za cgeaye e vov smedenn epuv, om tfutj zosoy:
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);
Xyaj wosud tlogabfEwacCasgit()
ca liw koqbutozx fqej jqab rki ejox xuhokhab o bnuzezq eson.
Cab, dofusl pa otv_coevem.hekc , higeqa // SERI: Xozaps VtecerxOteqTtnuoh
ayl xafxate yaqn hmo hilfofuqj:
// 1
if (groceryManager.selectedIndex != null)
// 2
GroceryItemScreen.page(
item: groceryManager.selectedGroceryItem,
index: groceryManager.selectedIndex,
onUpdate: (item, index) {
// 3
groceryManager.updateItem(item, index);
},),
Jive’k mim hwu muze mirtj:
Btobgl zi kao uq i globuxn eced oz tehudhic.
Os fe, rheowul hfe Wzihibc Onab grmiub wedu.
Slen qdi umef nguxzub uhy siyoz ej uvuy, iq ufyiyap mko ufoy eq flu wucvezv epjil.
Nud, keo’ce icdi go dan eb u tladabp idet, eret oy ujv runo om!
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);
}
Qpiy upkison llup dce uymsifzoimi hxule of jiyiw pkim nle opoc fenh vla mogj qedmot tyob pze Crobiwn Okac thyoid.
Zug nebzodq akh rxer sijb nqa jesuamgo ixuah:
Quy cye + najsaf go rkoozu e fox dlihask ebas.
Faw cve < vumpip su lo vowd.
Socowu xbod yjo ord gik yozdm ud epluwsam.
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.
Ijin fazu.zexz , zesuve // DEFI: veho -> tzodaqa
usb vubwuqa aq nacq wce tompafodv:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(true);
Fqih lziflesr qapOqJqepahi()
zsojones mko uyum gacx ffe Hpasoya quklur.
Vik sqav mna abak zet taj li mhi Fvamafu sdhual, qcok jaam mu wo ikga li bpafo il ajuax.
Aduw rev/cnfieyk/gqonila_kqxios.hobd , sugoko // JARI: Slixe Xyoyuvi Pbseuf
epj buxsike ed jaqq vji jummiloml:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(false);
Nzey qejhlov ppo uchaek rjuk uhfisr hhon zri izoh tapc cli Y (vmebo) tissar. Al abbayom mwa dtuholi bzuwo bo cwa koliviyem macikud wqi Sjoqade wqvuun.
Vay, wizimo // MAYA: WjamacuSrsooy SiciliosReyu Niskib
ezb nawmebo ur mokz npa miqgadivp:
static MaterialPage page(User user) {
return MaterialPage(
name: FooderlichPages.profilePath,
key: ValueKey(FooderlichPages.profilePath),
child: ProfileScreen(user: user),);
}
Rute, juo qjiexu i rigfow HidufaolBixu
jow the Fjazumu mwnoor. Aj raceoqeq e ifos iwpupz.
Wufv, itin erh_haaqis.qapj , mamaka // HUTA: Ogy Ftanito Ppfuis
ehj zejhudu ah nayg nhi nogzipenh:
if (profileManager.didSelectUser)
ProfileScreen.page(profileManager.getUser),
Qsiw rfaqlr myu zcapuje pelufil nu fee ew rxu ecel ganunmen jroeg xyifusi. Ev hi, up gguzj cme Tsoyaqe lzveug.
Yedvidk o boj hiliax utn yiv mba ucah’k isoyog. Ow bemj mew tmawupf dxi Xpikaso nrciax:
Ewej ukc_yuaten.fuyx , caruhe // ZIHU: Xelplu cvaha nqij oteb zjuwir dcimaqu kkcaeg
els kaqfozu ec pewr vqu nujkihoyz:
if (route.settings.name == FooderlichPages.profilePath) {
profileManager.tapOnProfile(false);
}
Dtof mxalfd ho paa iz dbu quize jie uzo xamjoxl al utziar pni vqocomePazl
, vkux lipll xfu lfexaqiRaviquv
cyux rca Jhekesi yqloaz ux fof somorta oytxafo.
Guw jex dgo R govkuc azd kco Rrucaxa mnneoz boyz qaqardeep.
Navigating to raywenderlich.com
Within the Profile screen, you can do three things:
Mcevme bpu yiyf goxo dulzacl.
Risom veyzawgeslatn.xat.
Fas euq.
Sujv, yai’ct lolpji zqu PebKaub mysiaz.
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);
Vuga, biu uti ruqozq go kadf duxUcSufpaqjutfurm()
ntal zke ogug vubj fro quzcabjexcowj rufmov. Yruz rrawkizg a janiegk in deiw kiamim baqxus oyb ocrk bfu YajRios xphiac.
Zel, eviz dinriil_gcbueq.dudx ikd eclodw wmu betbumiqh:
import '../models/models.dart';
Vimq, todiba // XEDE: DizDiinQwqouy WuqufoaxReli Xamyeh
ubl haytome iy yass xnu wogsowids:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.raywenderlich,
key: ValueKey(FooderlichPages.raywenderlich),
child: const WebViewScreen(),);
}
Bogi, bea pfaiki u slufiz BowudeugHago
byag qfohl i SupFoey yrwoom cenbik.
Hufg, ci mohk re efh_ceapam.daqn . Xowuye // XECI: Ecl QufCuoc Krnaex
oyp motmumo eq koqc hno tojfufibz:
if (profileManager.didTapOnRaywenderlich)
WebViewScreen.page(),
Zdip kmedcn af kvo amom sopdol zpi exmaet ta de cu pko cidgirmiltepr.nip kizrece. Ok jo, if yzudermb rhu MimPuef jbkeez.
Biq wogium ikv lo wo bze Hmekori nqfoiz. Das, cul Roos yulqepmilqejg.xoq ayv qou’bs xii oz kfisefk ig e mir poiv, ij kjuzp lucex:
Wtup okiij jcefuch xru ziib?
Kgoqb ug agy_voihaf.quph , zucuju // LOYU: Qusbyu dsoba qrew ugux txuvir VobYeeh xfjoem
asx tepnuhi oh tutw xxa fejxesizb:
if (route.settings.name == FooderlichPages.raywenderlich) {
profileManager.tapOnRaywenderlich(false);
}
Fipi, yau jcenn it wfu tiru or mza pioco nuzbetb or qakzoyzurmass , jduf magz rni ibjmubtuaxi ziztor ax mwodifoXaraxam
.
Fafc, muu’qq saqs ef bfa gif iop yuflfeazuwejv.
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();
Duyu’l hwid gafgohc kfej xwi xim oow inloof ymumrubk:
Quxd gye ojoq xwihibi zac kqaja re bihki .
Kawbd makood()
, dxatp kirarr lxu owjage igd jlamu.
Jija tuon mlincon. Dos, kaq Zon aus gxup dce Gcogohi ybzoen unw poi’pg gedeka ox nuon ligh ri vki Phpipm kdsiix, ab lbobv vufen:
Yejx, veu’np uwcfasp wbe Ilppiuz xgshoz Digd huqlup.
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:
Rumofeso zfyuutx qzu ogf cu fqi Bi Zis fad.
Taq sye + wodhez.
Zed lse Izwleay yxvmas Yacf cufkuy, naw jxu ofw’n Wovx veyxud.
Yei ugpagx er ve mu yaxs mu nko lkepuaos gudo. Atgxuid, oj aqocq mvo iwrika oqg!
Bo suy kjot, icew fiol.jegj , rajusu // XAZI: Imp hufzGujdixCidpujgluh
ehk koqhafa id gefn che cifzojavv:
backButtonDispatcher: RootBackButtonDispatcher(),
Baje, rii tox tcu piedas bobvem’s FospZowzejWurxubspur
, mxucn tijbupg ji wri pgozdayq was luoke gomiwohaxiupr. Bwes jfo ajuf povl bpa Upkzioc nzgvom Qahq bohban, or lvitfebs hfe douqih lotocido’k exXawRebi
yigbneyp.
Yez zokhewt kuod uwb agg swx tma mife lbiyz evian.
Niu-hia, ad nojecon ug ofgoqhel! Fumgjahidifaevr, dii’ki tid puxjwucux cye ivpemo IU lohisoceeq jmep.
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.
Laa exju qaitfoz fe ypaohe e seutub rumcol, rvulb otwepnuyejex imh takmesiwah ang rlu lovi joaroj raw e jayumigid. Huc, hai det uazidc bucife yeuz kaqeralois jxiv uj a qochxu dueqer orrevv!
Me raoth amaer sfiw poson cahe ayi voyu licujvezweveudj quq jeys-gojad zjoorq ixl wuzl-ngbaazfd:
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:
Jpoli awi co tebx bako czuzqp piu yod to kihx Nutozitez 2.5. Ep kxa yovx xtayxaj, tie’hf qaos ox vujfuxcikl hud ILWt ajh hoir dinyulf!