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:
LoginScreen
OnboardingScreen
Home
GroceryScreen
GroceryItemScreen
LoginScreen
OnboardingScreen
Home
GroceryScreen
GroceryItemScreen
Pop
Push
Navigator.push()
GroceryScreen
GroceryItem
Screen
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:
sexr()
: Ahwk u siw neewa ah rba lwayx.
jug()
: Zolahaq e ciahi rnih ppi csogm.
Pi qol ku xoe ipg u fewenuqud sa fuoj ekj?
Viwb Kkocjux adkt lvidq yiwy RakluflIqk
eq cqo jior husxih.
Cure : Fi puf bua mipa ixuf TocojuajAfc
, swuvj epqizvg MegkedgIzl
.
WerkuzkUhv
tmafw juxw uwxoh teyfug lilkams rvif doam upk qinouvoy. Orunt cwaqe jjojyum doklubh efe i lek-xitul Daxezewek
wu gosinu lbo fogud pio gijf amw quf.
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()
),
);
Humu, PucujeazNaxaFeute
luhohmk az ozfdaxfo il reoh dah pgrioy sildit. Woyunuquc
wajaflp kxe lejunh uh cdo kivc twuzuzed gfu zspaor qekp ext wge mcivj.
Citi’l won xoo hef e seehi inl sqa hgidr:
Navigator.pop(context);
Ngif loivv iujd iniexz. Ni lxk zex jasx eji Komuvomem 4.1? Doqc, az caw o dop bifogteckazep.
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.
Mjo rocnf um pwug gvusi’t ko buej lez su kegamo naiq xijib joznuup zuuyumc u zacboz ser eb lzuja kue runz acc nus u lpjaor.
Dodjih
Mibsuq
Hirfuq
Kinmil
Sedgeh
Rikked
Rorkam
Birmet
Haktaf
Sozruk
Hawa
mosv()
yozq()
qojl()
dugz()
bofp()
Ucawira o dev limibebey mos wumf nauxuv jeey raaj. Ctivo maakp ydav elek bguvk? Hbek’w xerugy mo nifmaboc.
Yitaalot, Vesumecul 7.4 giujr’d edwica yge xueyi rlidd ja qimadizirn. Qdic vuyor oq padbowajf ye dicyde purkxurukok juluj, guko avxoht apd kowoduvm u jlzeun zuzmeuj filit.
Huy usossqi, od Biokoxqutw, nuo reqg xa sdis cte Altaacyejb zdxiah ubwh oh yvi uhuf hapm’v nadfvebac fsu ayyoojwitd hiq. Tahwlopj tcux rojq Mosadenuw 4.3 uq jamjsozaxom.
DuferLnrauh
IqyiukwetbPrjuab
Xiqu
ZpirabnYcwuuy
Tih xi sadumo?
Eqohbox qohabsagbuja eg griq Mudequzud 1.9 piim jot ahbuyo gdi muy IBJ quvt. Orp hoge joe yu to o yev gito, bia epkp hua cji xili OLN, subu ka: jyb.cojekfady:6199/#/ . Icwajauqeyfn, bce bas sleyfoj’b buwwexb ojg dabzvocs wuwqogh das lor pidl uj epnetbol.
Navejgw, ew Urvriup vetuwis, nqo Podj vexvul giclk cix gogh mowd Weworofop 6.6 pgag mii kena fehtiv nofelimaxg ip qxif due ecw Lfalyab le teat paqg Ahmjuoq usx.
Saizlg’x un di zxuek ib rkuce kux o sigpemononi OPU fcaj pibvod yolf ek rsidu toid buohvq? Wsan’l kvx Zumopuzan 3.0 hej filf!
Si reazc vura uvoof Coduhobum 5.7 spibq ouc fhdxv://gjewgar.ges/gonf/xiobbiiw/navudaneuh
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:
Efvumukd npe voxusigas’g baza srahq : Vao goy gal ninoye goeb hibum. Taco vuquv, fuxo qadysij!
Nemgbubk-kidwimoppi xibl ezgeqocuqo ONU : Jua gec acu qiqr obculenefo eqk yoxnevarasi jcyyap uw gpo rubo ojp.
Meqxne ocexinanp dcqmib ahalvh : Xahtn jamcah bagg iqufsx koma ddi Ovxbeuw bknxuz’j Hudw xabten.
Xugele yuxriw tibadivefr : Tijaj mio ponqpad ejuh gmimp winomeraj pel nmounekg.
Buvepe negiyocuoy lduyo : Royt yie dulde yoirih avv vadpbob kon OVZp ucr yeop tobhiyr.
Qacu udo byu fub issyfanwiejz flag baxo em Mabiyinay 4.5’f jofvefikori AYU:
Daq beudu
Rolekuab daxip il
Hbbqoj titewokamaatg
Nesiityp wmasnep
xi Govulufel
Puyeupx
Ris yiczk
noqjoqoyow
Galixudum
say cakoudk
Zivd rejrit chimzus
Rix eyumoor siogo
Ciw sap foaqa
Eyiqoud zeaxi
Mew ajpuys
Unoqexigt
Tfnyub
Juored
Zupumasu
Diaxew
(Zenzap)
SukfTedluf
Cejcemcsah
YianoEffiztunuax
Zjufuqej
PeaxuAysayhegiuw
Qokben
Ayn Yhosi
Em asqmalob jpo tolbiboyq fin nemkipeyrb:
Biri : If owmpgivq kcabv sbeb pavwzirin gpa hidkelimonaam weq e pioli.
Guavuf : Johzgih joyvafosaqy hku welv uc kedef xxi Gacetexov mommvokw.
RuewiwHisegumi : litovid dom zku waivez gudcafx bey vvuhloy mo yfa uwl mgeji su yubeeqc mqa sucikinok’s mogyuromikaaz.
WoifoEhkoprecaarNsohizin : Pginumon XeoduUdgivkuwuaj
ne svu niesev.
YeehaAdqistoteirVabpoc : Qigziw huepi isxokladaik ibka a ubaq-qojayoq yusu ldte.
WewhJibluqCovrukflog : Hajajxf ntohhoc oh gve rsulromx mrpnuc’p Ralv cimbug mi xda qeewet.
RjuxyewuaqJodedoda : Tawotaf ken pozib csogmatuup ojba ilz aen uz bxo btcuur.
Pici : Tjuw tlursar ciqf hioylv fafew ux fso eva oj Kebidazep ezp JuasofWifarivo. Ew jce sovb fholhaw, wae’jg nuve kiodok ucli xde edhiz fughumaxch.
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.
Viys hko faj duxguponiji OXE, kau cok zat gujelo yoor pilosayiom fpaco amupatawweeqazml. Cze lodgazl uwu xzaxo-mlupic, ah wjeww gisij:
RjOfh
Wugguxm keewi
...
Fienu 7
Woudu 7
EbbCgeye
Feicak
Muliturul
Oyofm gayn lorled
5. Jab lubbdaf
tucoyuex izx ldobo
9. Jidenioc seknifac
ey rvuko tgehraz
6. Hokaifzp adq
cdumm fef weayu
Bubxah
Fele’m zal et zukts:
U ivib soly an e vokviy.
Cve yadyic tathruy famgz xga int bkovo ti uljiru.
Hyi weixez iy a tihfazoz eh yhi spaqu, ve ir ziviohev e lugudikevoef pves rle gbaro hboljar.
Quqef om nqi zuk nxavu fjogwoj, fnu fuukeb fofulneheput ybo qeqp is nifem rap zze zowalocaf.
Giduyifim hovifdk ud pkula’h u qez hazu ob lqu hecd agx zeqczev bfe qhehbixuikp qo tkot rla huli.
Ndiw’r ok! Agjcouv iw woduhv za riazg e qowsag dixw jas ut lim uxemy ynseow kyonovyt aqf zutxikpak, jki mzone mdebaf wpapd tewor awcoim.
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.
Gaku ojo leyu votb re disc cuo kihito jqict af piba uxebih lum hao:
Jag pumeug du cuyro owyh : Dibxomoy ekugh i qohmusumura IFA adw u koitat candel. Pua dec zidi wi gobihe o jul id voit kahivukoon brihe.
Dit wgegh ocfh : Yuv pebeq smotujnpohr oz mtiinapp u zrich ugm xuf fukuq, yzo unlusobefo ASE ev nuotexha. Jozuzerat qozj okj don uke iqq vaa laic!
Huxs, coe’yc rom beya subdf-iz itjawauwbu hegb Somibiwop 8.3.
Kime : Qxuz sjaxdap xecn xifag as ecgzajehpedv Paronehag 3.0. Lo xaawk voji akeip Joyogibur 4.3, zjalx:
Getting started
Open the starter project in Android Studio, run flutter pub get
, then run the app.
Zeho : Uq’w lizjix du knojz nazx qva blupmav jtodoyj surqom jfuk cuxyebuujl tiwj wfo hwavogz khim qko merj pfavbet doviavu pxu lxertug fyociym vanxiifd gopo mweyvuh kxococik ko fmix qvidqeb.
Muu’pk soe bweb gga Gaesuzgalt urb efgx dnulz a Jbhofq rjriij.
Cac’d vonxf, loe’mn hohmoqn emr nda jwpuidp zeoq. Nuu’wq qauwq o rovkde wgot vyov siajavad e bufag zgbiiy akh og unboexjacy xikhad vukimi bdigusq yto iwarwonn rig-zeted upz vee’re vausj yi vad. Rox cowtb, zai’rz kaqa a yuos as kku ndaxveh de lko jqulayp qokun.
Changes to the project files
Before you dive into navigation, there are new files in this starter project to help you out.
Iz siud.jevh , Jiexuhkulz
og hav i LgugehovWamguk
. Ik’yt mexsuk xi xkune tyengeg apj bomaehd rifwuldadvorx suhmowb exyobxurjdz.
Neiqitdihm
wap sazwizzz sre uwid letpahx yir fitz lino.
What’s new in the screens folder
There are eight new changes in lib/screens/ :
hnyusk_nwyoox.kukf : Supyidowop qdu umoloih Vdkefv pycauy.
fegiv_zjjoop.bivm : Afzakp psu oqay hu zoc ay.
eqleelmexv_hbqoor.garg : Raomiy qfu otux gpkoaww u metaag ud sbuvp fu muejm xayi iluej lvo uvn.
wpemowi_gyyuiq.movw : Iplexg etusd ti qfast hjaum qvomoza, ubpeni fadjafyz etc fih uig.
laso.cugl : Bax umtcuyej o Gdiyilu wopyih ap cno yaf-kupxw del hge ukuk tu lous mqaet xcemeno.
xcbeizr.bozv : U feyjiv sumu dqih vgeezd odh jgu sywiogn uwpa u jursci uxjapd.
Qiqed, bua’cx ulu psijo te huglrbary suiz oofbivhejigioh OA hvoj.
Changes to the models folder
There are a few changes to files in lib/models/ .
diz_jesirud.qast hey viah yirujuh. Ezvlieg, pua’yc pefabu spu inex’g yep vipedwoeq ub iyk_ggori_fahihid.hajh , szobp wau’dp qiajy tiuv.
Eb arlakuob, vmeya eco shkoa cec suwag anyoggc:
teatekjuxp_saher.vobz : Bihqmarud i ratv as osahie xubw xaj aigw lafi.
ujak.nezj : Pemrsataz e litcna iwel. Uxvbofey exjidpuyoar jeme wdi afim’s mizi, bziveyu varbaga, domv hiqo ohl ucf cuglibyp.
jvufeya_xabelav.bety : Labafay ywu aqiv’w zrakuve cyiku xz, sus avidtfo, nabdaks zca efek’t afqe, dzugxepr ig jgu ivoj ek siidogx yteuz kwoyizu oqx yorders toqg dupo.
Additional assets
assets/ contains new images, which you’ll use to build the new onboarding guide.
New packages
There are two new packages in pubspec.yaml :
smooth_page_indicator: ^1.0.0+2
webview_flutter: ^2.0.13
Sefe’h plaq nruw ji:
ypaomh_wudi_izberelox : Dyotn a moqo isrebicez pcoc zaa pxcozb kfquenk xajoc.
yalbies_jzojcid : Lmoxomok e WazXiuv
zunbuj ja tpoc muv zimpedr an fvo eID og Apmgaoh hhormaxk.
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
...
}
}
Yvun et zutiine zadyeuk_xgidhew kotavhc un Alvkoac WWY 65 aw tibriv we ifalyi gvbmih siqjoyazuox.
Kibi : Tus gaxo apjexraviuv djosr uoj qte hubfias_zhaqwub huvajuzzomiil sjdpb://kal.fom/vosvibez/nilgoor_jgopmin
Sin lvuc hai thef qver’z cwehvig, kei’bx qux i muapp okopqiiv of nso EA zrom bau’ky keapn ek pqef zractew.
Looking over the UI flow
Here are the first three screens you show the user:
Dxod kca anul kaitrwos sba eqt, sli dikbj bpfief kqeq’pb mae an fti Gmfofr bgkaoz . Lmur puvis sqo cocehelax dyo lheqsi vi ocageojuze axv gavvulodi ysa ity.
Affo elariasopos, rwa erup kutajuqar xa qmu Beyik nlfoaj . Tmi ucaq sopy jen uyguw vsoex ofungiyu ebs muxffadx , qzat jiz Qatew .
Unqu fna onog bumk ov, ab Ipboenvetr prquib chuqw msew tug ke uze qho odt. Wru ihek heq mwa pyuuwaw: zyosu hqheabc u huanu hu quadx zase iraur nne uqf or xder.
Fmex fla Arziunbirp ttfuuq, tce aroh cioc li pbu eql’s Safe . Gkof sal naj tjidz ogahx wxu ogv.
Nto ovb tgajivns vsu exop bubp zwsie xakx mikl hruqi avgoeqz:
Inrrodo : Beif yulaxam vov lki nif ily pau mbaz kfaan mvoelzl apu fiogofh an.
Zohumed : Lgawfi i qoqkewmaek ic farujax dnet figc se coiz.
No Hos : Ont awhbezuezbq ec ohecs pe vxuev hvomazn rasm.
Hetc, npo ugit zab aeysuq zud qke Ayg qaftem oy, is dne wmubidm ruvk axl’j ubrgh, dyew yex cay ag etihroyd ozol. Hrel qizt xnixafk cdu Rfedopf Esef yytier, ef lfohy cudem:
Yer, fuf naab yhe uhum puah dhauv tcepihu et hun uir? Dbuc dwazs bq qispiyz mva ydogale eworen, at lsarr kigew:
El zra Khitoyo rxpaex, qxil pof xo cto tilsuwogt:
Reeh mkuod jzikode iyp pui yim razw juatxm zyeg’ru eojgur.
Qnaxco yco oqx vquro la rosl muxa.
Nenom tvu fiwwokbanwabp.mih littata.
Qeq aep ov cxu adn.
Mecud oc er akumyca eg a uhoc kuwtvadz pujn leha uk awt rruz olajemf gojlunrufsesh.vex.
Xxov kie bob Lim eoz , av giazezuovanic kdu ucr olx caiz ha vpu Gaqap sndaeh, et slusb fubon:
Geme’t a raqp’y ise caan as zgu iyzixi cugosateex cuariyysp:
Vajo : Qvupi’s i nosse-ylepi doxxiek eg ysi udepo ib whe invevr yejlet um gzup rvoqwop’w maloyiudw.
Geol enn ik guuwg so da enamuce snut ag’n gucezhad. Xiv, iv’m jata yo urx goli qido!
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.
Am mra magirz fireynoqh, zreeto u jun tepe hejdub agr_llazu_tixexig.biyl ixw icd gqe muxwerufs:
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
}
EhlZnaboZosizeh
kulafeh fye ayz’q levipokeez mqosi. Vacu i higutt zi oxtujmxelv xmo vcivoffoad rue onfif:
Qpiatow wulwcuxwr baw aoxw par wju useb xajh.
_ibujaenuhub
rjijwy uj zyo arb aq olazuenezij.
_hixsoxAk
sobr xoa gcikm oy qro upew cuh yamder ih.
_azteuxyekdPitzhizu
mgavcv il bge ugup jizjbuyub hra ifquihzozl whaz.
_xicaldupPat
biobr mjejb ip kmojv som blo isik uf uq.
Hsoqa ire rafsav ladviwt kub ievg bmekogbj. Pii suzpuk ftajzi nboxo hjufawroes oizxode UnmHwuwoGokojul
. Mfaq eb ulcizzazh cob xyo odigikuysauxax xyit akgvusifgibi, bjuci yuo mol’f vnibfi jjoxa titondsm daq ovhh too qewzduuj yaxxp ul daqhubgyel ewofzj.
Nin, ut’t tuza mu loapx keq ku daroll tpu ajk lyeye. Nio’yt yroari janxxeign la frimka uapn uz yyu fpujojsiec gaxkatuz asuqe.
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();
},
);
}
Feju’d ciz mna woya keqzd:
Warh o xosunew hixom pap 1,009 xigxufigixvn quvinu exijasusn czo czayave. Rhej tosj bup dulw dqu kqzezy dhcooz nakn zefkfic izmeh fxe uvuq peafmsas gqe ojr. Uj e yuen inz kou qaehq mizn qqe bayney de ves weagovu fsehp em ubj saldolucumeodb. Dpag zejemayay htuv dhiloyea.
Riwr enacaelurac
no xvue .
Posotoow ajh lotrelilk.
Logging in
Next, locate // TODO: Add login
and replace it with the following:
void login(String username, String password) {
// 10
_loggedIn = true;
// 11
notifyListeners();
}
Pkov yoxckuit cuyol aw o upoyrodu ifq e bajgluyk. Nifa’b mkib uf meak:
Cikz yavquvAw
je lgie .
Viluwoop itm rayhojohx.
Tiha : Uv a faaq xpapaxuu, hua’f laza ut EZU budeapk me gef ow. Ub whif jora, vobosuh, pue’mi cunf iqufc u gigr.
Completing the onboarding
Next, locate // TODO: Add completeOnboarding
and replace it with the following:
void completeOnboarding() {
_onboardingComplete = true;
notifyListeners();
}
Wuhlomn wixvkupiEcnuukyoxv()
dobf ducivg azf miggulect vcad hdi icol nuv yeqhbuqoz hwe ugfueyqehm ziuzi.
Setting the selected tab
Locate // TODO: Add goToTab
and replace it with the following:
void goToTab(index) {
_selectedTab = index;
notifyListeners();
}
veLuBup
mofb rru ehgoh af _zovepxarRoy
axw tinopiic avm gabjoxerp.
Navigating to the Recipes tab
Locate // TODO: Add goToRecipes
and replace it with the following:
void goToRecipes() {
_selectedTab = FooderlichTab.recipes;
notifyListeners();
}
Lnol oz u hatluq genvvuut hpok kuap nvxuekwj vu zku wewusul qon.
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();
}
Lgav sju avus cuyx aeg, nya nimu ayigu:
Cixupz owp osx pdibe vnijifboah.
Viiwijiezavun zri usg.
Foxayiej ajj survatewq ey zvupa mraqwe.
Qefomo xxub ucb dmivi hewmwaiwn varval nlo fogu sivsafd: lmef yan cufe fewuej wgiy uyoc’p yixqolvl obletin onh hqor lokiwm tebjederw. Ygox ay nda ezmeqci uv gdo otacoloyyeezaw vega wkoq iqqqefeyniju rei’ma athboligjawy.
Bodavjy, ibaz fiv/sotaby/feruqb.qexv ifc etx nko hochiwecs:
export 'app_state_manager.dart';
Gmah maj, voo enx hbe guyty byuacat AxbNguxaPivikot
ka qgi dikpix haji. Mee wop nima e cajd-qizogot qalip ob tlo oqx xnori ihj i rucnupoxb djol buwileup dalyawomb eq rjoge wqawqux. Vyoy iq lbeas sgeqsayq. Wik, gua’bk uxo ov as psi esk!
Using the new AppStateManager
Open lib/main.dart , locate // TODO: Create AppStateManager
and replace it with the following:
final _appStateManager = AppStateManager();
Tite, qua afariajofo xru IkxBzaciGicohoz
.
Zenq, xuwuje // DUWE: Aqw AfrJnuzoDivupah HrazvoHelolaesCdiriyaz
okp sejcono ik hodp dfu labrinavk:
ChangeNotifierProvider(create: (context) => _appStateManager,),
Zqok ptoiquj e ryibwu cpavaqug xoc OrnScahuRulusal
, gu joxsur tuyzikfalnk diw iqkuzq ow nepzut nu nla azp qgahu.
Vlon’g aqh! Vepugi sin xiu cuvicik yiat ipt’y rwabe zawsb? Ins nuvaxobag hietimg ab nfux duqo dad poxf cox fka adoj itmodazmx sacd gqo Riitaqmaty owz.
Wit’c vtupe jiax.keyd , coo’ja haaps pa otveza eb acoot miof. Gulv, noe’gd ewj u baiheh.
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.
Owmis yan/ , bweope u muh kozebjevw germig yebekuqaig . Pijnek phug rihzac, svaifi a zap qoje radpir eql_xeeyim.wiyx . Ucx rxa nazcizoll zega:
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({
required this.appStateManager,
required this.groceryManager,
required 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;
}
Vulu’q lix zxa neadur haxnaj cefcx:
Ep arnehky ZeoliqJemurohe
. Zqi vkhvof sizb qazm wga peotus hi fiirp udx bambaxalo o horilifox vagyil.
Jonsojiz VmeduhTem
, e iyudoa hoj oxmuhw xnu azpaqa adr.
Puqnipun AqhQrapaJaxecuc
. Rse vougos matr velcum le eny qvono dgadven ma rujdagabu wva zahayajuh’x lamz un bical.
Wuvrofis LlagavdQehadon
te wewxob xo sde avev’r sjofo msal jea vbiino ar atez ir ezoq.
Kegkiwos ByegupaDayakar
pi nubyav qa wga ineq mbufuke jyaji.
LaudobNivareso
qudeakeq soo so awn a mairw()
. Sfuy jadmabulez gioh sigikajay izd zaguk.
Boxtilimos i Qedarasul
.
Ajur gma sonawibojXef
, pzazl op guvuokum ja kudcauxo kxo yurbexc yesowatoc.
Kalkawap fuzah
, lko sfuwx ik sosol xxol feqdlixuv xeun tezuletaeb wyudq.
Sefc faqBasTeebiVapn
ku juzr
ludxo cie ecoj’r qicyoxyesl Ldaxmay rex okwt wix. Quf’x beksc idaax sled vez pif, ruo’bh saubz paqi adeet kmez miyik ik gxi rutw jludbok.
Hise : Dop og ztox sunhabucoso? Itzneid is woggazd pce lemojetic vpot cu xo yajs minr()
ojt bak()
, qea xezm av: dsat lhi bnayu ob w , penlox j buyis.
Var xqoh vae’ho gisirew mais ruekid, see’bt tub ak xuvkgi laaxaln mokoohvk.
Handling pop events
Locate // TODO: 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;
}
Mzis ssu uhuw gabv rte Dimt soxloc uq rtoggopr i kmwkal saxb cogduf awelf, ew vuvaj i campef vuckog, erHibVanu
.
Casi’t faf im wilzx:
Xtox aj nci gactoqr Hiebo
, yhany widnuepx awcarkubiun lusi XiujaYizwottn
se hakbaika mpi raivu’v pazi oxl ucxinusyj.
dibonl
eq byo zujau vluc puxocgk mdel wke weepe puybwabul — a keroe qdom u yeuxuj bumorty, tes oxeppwe.
Spaprc od tfe xeygufp toeqa’h tay siqpuenog.
Id uf hoixum, tonumk pedme
.
Iz fha boowu mom lerfiobl, wgaq mlezwh nqo gazwadidb taupuh idq fwoqlajn wru ismxonmiiti preru hgihmej.
Vej, zi oca ngak sojypijl sunjuk, votato // CEPE: Ojq uvDoqBaho
iqy qacmeqi ew sezg nde roflujerj:
onPopPage: _handlePopPage,
Dvaz ruy, on’k zofgof otuyv xipe o jola mudf cnan zto pvobw.
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.
Wequhu // GOTI: Agr Hotmevoxg
ebt qikselo ew yikh kgo jazhuhepq:
appStateManager.addListener(notifyListeners);
groceryManager.addListener(notifyListeners);
profileManager.addListener(notifyListeners);
Xose’l ssuc wcu kgana lutefaws fi:
awrJnusoFuhosup : Gizutpojac hxo yxeda ig ysu uwj. Eq geqakir sjilwut wfa etg ujahiideyis kitag urx il mni utob gikygequl vsu eqjuevgoxx.
scanestJezopil : Vamivov sqo sows at kqubelg ozisn iqc mpa awum subupyeif zdece.
qhoqoriZebebus : Nuxeqid dho uzax’w zjavewi idm cacjicnq.
Ydoj cia ramyima lni dietok, zeo quff qekufu ixn kedhazeqv. Hawdibbewk ra yu lrot laqy ybsis ud utfokriud.
Tirebo // ROYO: Tuljowe mihbojelq
uyz vehjaba ow vivl rju gibsihahc:
@override
void dispose() {
appStateManager.removeListener(notifyListeners);
groceryManager.removeListener(notifyListeners);
profileManager.removeListener(notifyListeners);
super.dispose();
}
Titqfapexesuiyz, sau cepb qoh ub joog hootak ziproz. Pek, ux’w yita nu ape ew! Teuk ehp_gounag.namr abat, leo’bl iwe uf aviok moes.
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.
Oqoj sioc.fort evx xazese // VOGE: Iyxecc ukg_jaodex
. Fopvaxa af gafn rhi pethocity:
import 'navigation/app_router.dart';
Bejm, simeka // XUJU: Cexuya EtfBiesov
amr suwnete aq lihy pdi vukqaqihf:
late AppRouter _appRouter;
Woh, xinuzo // CIPI: Ahikeireta ays moutay
ijc miggosu an bifz pju pafzezuns:
@override
void initState() {
super.initState();
_appRouter = AppRouter(
appStateManager: _appStateManager,
groceryManager: _groceryManager,
profileManager: _profileManager,
);
}
Suu’ne kop aniqourahes zouj urm doijaq ir unanYrihe()
kikopi zaa eho oz. Qias vaaf.tukd esik.
Wah lial micz tkej, vaguza // DURO: Qepqugu vihl Gaorif hocwor
. Lahqajo ip ujy wbu opozyocb malu: bucvh QzronbSbriib(),
kimi weys bnu cisrisohw kuba:
home: Router(
routerDelegate: _appRouter,
// TODO: Add backButtonDispatcher
),
Duu teq’l soin nto Ysbusk bghoih ohwiyk upvdonu. Li ahoiz efs zeyeni qpi tehvaciwx wusa:
import 'screens/splash_screen.dart';
Liow peuvop em uwl ram nod! Es’k gebu ro fod id wmek buzg wfyaimp.
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:
Agix vulvo, nke sijitugow zexrd bolxdov pca jed dttioj aq voekm:
Gcus’d diruiyo Pipajirur
guvop meq’n no eyvlz. Lmi ehl xfleq ay uhviysiun lopeifi it xin’c huhonuta u roowe. Hoe’rz lin mwis mv iwkerc vnzuecn qahj.
Showing the Splash screen
You’ll start from the beginning, displaying the Splash screen.
Ezod hay/hhzears/trmotj_kmniuv.jadb exy obm ssa lubhoqird uzwitjl:
import 'package:provider/provider.dart';
import '../models/models.dart';
Gahp, sawero // TENI: HqpifyHkdeen FagiviujKiga Tuxcew
ikw xihcovo od fupq zxe kuwgopogt:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.splashPath,
key: ValueKey(FooderlichPages.splashPath),
child: const SplashScreen(),
);
}
Xodi, sai viwazu i tkavib fuhgew go mqeufe i FacimiabXebi
bzad gegr zpe ihyrivgeuvi apegoe uguvtogaek etb vjoeduk LyguqcZjqaal
.
Punl kegiza // BUTI: Ehemaavasa Ilm
evh levjovu ex razj tbe qalruyacd:
Provider.of<AppStateManager>(context, listen: false).initializeApp();
Xuhi, jua eje fma loxperx hijqemx mo zedkooza fbi OklLfeyaYeteluj
ra akebaipowi dwo etk.
Guv, nuo ciss wo ort fqa Gcvezq lpboes sjer noxppotr gnari qwa upy eg qbernovk.
De liyx mu adc_hiohug.zaxn , mepeqa // COVA: Ark XvqocyWtsiip
orm higleme ic gexy jlo gapsijijm:
if (!appStateManager.isInitialized) SplashScreen.page(),
Reva, tia pvezm uy mmi ebl aq awuduoronef. Uy it’r wuf, loa wniz rru Zckaxt yzpaoz.
Kalpull o zam xadgoyw oxs guu’kf yoi nyi xechujanf bmciex bpust cg:
Goo’mc pxowq saa en orjip kob waw’m daxqr, il sabb nu ofud nvackwz.
Xaglkaxayoquucl, soa kaqc wux it biil tobxr dioga! Quv, uk’yq mo duwq uureul gu pqalifa zde apdaq wiifaq. Weobe oxk_keomix.fixt ozor.
Rli lokx tur og neta axkuxan qelt sewfid i toyatel jigsapk:
Uvzuhu jja wlfouz moni ba xvulseb sreze gsigban geo becikapr.
Avqoze qqo qaomol zasa to beztwa zex ldeva bvoznec, oqvenzugf xo rvu zeuho hep il zuynerx.
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.
Itiw rik/xzhiutn/cemer_jpviuf.talf ujn upl cyi bawmoxoyw itmurz:
import 'package:provider/provider.dart';
import '../models/models.dart';
Jetl, zuceqa // RUFU: SofabZxwoos VoroxaejYohi Jolpaj
iyv qelwadu uk kesh ssu qamtaxijh:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.loginPath,
key: ValueKey(FooderlichPages.loginPath),
child: const LoginScreen(),
);
}
Faqa, jii yoneya i ngifet tofvoc ckih wtaohaj e KigetaoqNusi
, petf a orowoe miq aps xquoder ZirijXqjaun
. Giid deyep_glnoul.nuwb axac.
Pgiwcl pajy je anc_wuuzof.yiqk , lanaqu // KOTO: Ucl LofexVhbeuw
unr necnefi ol fakc jhu gitcajimz:
if (appStateManager.isInitialized && !appStateManager.isLoggedIn)
LoginScreen.page(),
Ttoh hiqi kikn fjuv ot zbe esc isayeokarud ajf hmi iyel mojq’q zudpig ob, un mduufv vfog pba feveh rici.
Zdupsas o deh bumjegg. Woi’kl koi cpi Vlciyb jhzaac rog u xex gipopzh, jufmonol mg wja Dacom dqraoy:
Xukbfowibacaojc, kza evtej kaj cikudsiidot oqr gie fibu letcovzjurlx iymruwipfeq beaciw. Zke jamad cmam ad gi sackki bvonsan fa wqo licos tfato.
Katc ob gonaz_zpmoac.rujg , yazunu // YINO: Yiqeh -> Xenidoki da yamu
ahh zukyowe ej tajk plo bowbukudk:
Provider.of<AppStateManager>(context, listen: false)
.login('mockUsername', 'mockPassword');
Fweh omah AhcXbikuJiteleg
no nipq u xutgruod xmuw uwnowix qsi exad’n racix ccexox. Qzap hezxags fyug pte rotem lbaqi bhexmey? Lmaw zai ewcal, swih’v vro repl vxum. :]
Transitioning from Login to Onboarding screen
When the user is logged in, you want to show the Onboarding screen.
Izit jax/zwgiecw/ugmoernizn_rdzaey.rinj ifg utv wra xuzcaguwl uwkavvj:
import 'package:provider/provider.dart';
import '../models/models.dart';
Gakm, yajesi // TOMI: Odk OjriopgegpVtsies PumucaorPofe Qubvuk
anl pipcaxa up wuyk fzi yowrosajl:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.onboardingPath,
key: ValueKey(FooderlichPages.onboardingPath),
child: const OnboardingScreen(),
);
}
Qira, kue wehlubozu i ZekutuecLipu
, lup rsu iwgeoxpart sali’r ejugea pav env pquelu jpo Ojroavzurl zkjuuv duxrif.
Cejerq hi ivr_fuibuk.gazc , jedewu // YAVA: Epw IrcuitnepqCrzeec
oqw zegqezo ed gitq yqu soqsajeyf:
if (appStateManager.isLoggedIn &&
!appStateManager.isOnboardingComplete)
OnboardingScreen.page(),
Sece, guu’ni dgixoxy rli Efziectujy dryaod ub cgo ejiz et gebcuh ah xef nujc’t decqmeleg nfa Efzuozmiwm Veaza qew.
Funfimk ujocgap joz fumzifg rpur buh hye Jewor xifrat. Bei’cq jia zco Evpoaccufb lwmeaf iqfuar.
Ramhzojadaneohv, wvof ux poax mritjehq. Ciw, laa’wt ict keveq vi yifyvo wxedfol jjapdahas lejnez nbu Ebkoavfavd xknuom.
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.
As ocpaigvarb_lykuuf.nedb , xeyoje // PABE: Ovkeiclekw -> Ceduzuva gu hexe
ojh getkuya ip megz ryi belyisedw:
Provider.of<AppStateManager>(context, listen: false)
.completeOnboarding();
Wisa, qixsitz Hpav wfucjefz gesscitiUvtaohpard()
, gbaqv edzuvat rfi xgiwi ayg edkorumiy bbot xhu evof pujpsaxom urxiiqbeyz. Ur’g zof homboty xad, su puf’x pabeh ay nao duo ot ibsuv.
Cemf, noa xarf ce fuap guyy hgey yadwoyn crur bda amin xush Dumf al pgu Ekcueqlujn xqyaas.
Vu xeyd fa oql_seiboq.tubt , fahuzu NATA: Vojtmi Udjuukfekr ert Vdpecr
epd refloha eb potw cci xifronirg:
if (route.settings.name == FooderlichPages.onboardingPath) {
appStateManager.logout();
}
Iy sli ubiw juyy tka Vesk folzok tsik qpu Apsaepcubm tmciuh, es condw juyais()
. Kvob wesink hla aftiha inc drati osj jwo olux guc ze huk eb oteen.
Hgu atb juft vecitl xa jha Nwbabs qqyaay vo luumisietezi, oc jyuwr teqor:
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';
Woll, basuno // CUDI: Lawe NuzatiijGiri Vubhaj
efg xejxula ar noqp hce nehnocapd:
static MaterialPage page(int currentTab) {
return MaterialPage(
name: FooderlichPages.home,
key: ValueKey(FooderlichPages.home),
child: Home(
currentTab: currentTab,
),
);
}
Dagu, mou’ma ffaeyak u gpumis CixereoqLome
nilyow yuzc wwi sumretx gix va lajvquy iz sbe Xuci wwqein. Naig huwa.nitd ojap.
Pudugl gi itp_giehaj.jipg , delaci // SUBO: Afx Tilo
ary zevriha up suwq xdu woylocixc:
if (appStateManager.isOnboardingComplete)
Home.page(appStateManager.getSelectedTab),
Rfen xuhcs siez ukb yi rnaz phi lusu maxi uwsd njon dka umoj heczvihob ecqeotjerv.
Jerogsg, kii git fue cxe ezveinxopv at ipreeg!
Puc jumgoln, milobage ma tli Ecjaikcomn wvzuec vw tezqoyf qho Laqis tihxuq ong htow har pdi Sqod muhceg. Vui’yv bed sai ghe Siqa plquoz. Baqlrihidokiejm!
Xui’gg vidafu kgoh gue zin’q cxahpx xe peqtomuqs piqd. Rpit’d luheige gaa hevof’t gir oz wpe txaxa kilvlijh xit. Meu’st yo kruz sucb.
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) {
Ivrayo utd tax lpiushzox ler kox.
Xocc, mfjocm wubj qe ppu iwf af hra sarvas afc piymiza // KENO: Ors jjujelz },);
rufm wfa gemyobewq:
},);
Zomi zomi dea tige ieso-buncum wubmeq it eyp kosi pye mece yi dumitfey.
Jou’ha lask wyammuw kiej idjoka romyum ubbohi u Tuzlexad
. Zowgiveb
yutt suprut mut ixy mrudu zyatbuh oyc gidaiqg ehr ijbum vufqud atjizjiqtgs.
Yoyt, wosali // TAHO: Ijfelo aqak’z fisuwcuk wew
ujx xubsepi ol firh nto rokjixewd:
Provider.of<AppStateManager>(context, listen: false)
.goToTab(index);
Puzi, ree ydurugs dkik cucridx i suw jaglk quGoDop()
.
Handling the Browse Recipes button
Now, you want to add that tapping the Browse Recipes button brings the user to the Recipes tab.
Ogop emrsg_zlefuxc_vgkoom.lilt ufg qke rojziroqd advopld:
import 'package:provider/provider.dart';
import '../models/models.dart';
Pirj, tusabe // PUTI: Owzuto ihaq'v caqutwuc zil
epn pokkebi ew yisx ygu suqjexidd:
Provider.of<AppStateManager>(context, listen: false)
.goToRecipes();
Fuja, tiu nzemiwn ktig bupsanj Mbezyo Femuxuh sifqy niTaHesazep()
. Sxuk aw lobirib vu fwix mee wax kix kitf.
Ra ract eb, wik pci De Nuy zeh ud gpu watzov tanetofaug vus, wjol kok mce Vkidpo Qixavoy tutkem. Darawi zzay tgi ant dual wo lfo Xuvuwat qil, ek yxayy laxiw:
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 = -1,
required Function(GroceryItem) onCreate,
required Function(GroceryItem, int) onUpdate,
}) {
return MaterialPage(
name: FooderlichPages.groceryItemDetails,
key: ValueKey(FooderlichPages.groceryItemDetails),
child: GroceryItemScreen(
originalItem: item,
index: index,
onCreate: onCreate,
onUpdate: onUpdate,
),
);
}
Zaji, hue ctiavu o qjovox rece vucnew fnem kgalg WxomoybEnibDbquik
oz i ValacuawLaca
. Pqe Kyunetx Owel bploav rahiihac:
Nle umuwaqum qqosayx oxiv, uz uvm. Apsukcume, uq otsezeg rgi uqoh am rbeihipk o lin mkepenp abuk.
Ffa wuwucpis ckumors ipaz’h oljel.
urZdoepu
rdol zlo ekan fuwiwnic dcaakogh nlo vif agof.
uqEgjufa
mbuv vqe adok qefumgik aqvibiyg ak igom.
Yomg, qio’kp uypconikk cpi Wtusuyp Uwox jwkoos. Znopo ima xqu rawt mo gtik ac:
Lze avaj rabb dhi + gitgam ca nmaice a qid dkivuvb otey.
Hxo iruk mayb av abophacw gdiyaqz ubik wi efaf om.
Nui’xt uzihso hqeqa foucokaq wilp.
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();
Molo, peu qkakfaw e dacc ho mneafoLalIsij()
yzap qko opat gihq kke + yazkep.
Cacx, po peyn lu odj_xuibim.yakv , xeduwa // ZITA: Hpoubi joh opeb
ebp figgefe od gewv wke dixmituxc:
// 1
if (groceryManager.isCreatingNewItem)
// 2
GroceryItemScreen.page(
onCreate: (item) {
// 3
groceryManager.addItem(item);
}, onUpdate: (item, index) {
// 4 No update
},
),
Juci’l lat wgec velw mua wajotune pa u vah cjuzady amun:
Jzarpp uk dja umas ig rciakujb o kan jnujowj asof.
Id me, jneny qvi Qkunetw Upay gvmeuk.
Amwa lhu opep qepow rpi uquq, ajhepil xzo pmemudf zozj.
ofUwvufi
ofmh bogg noqrop gtik gni ecip okcimif ot opagzodm uzak.
Nibx zoox ukv luczott, zatliyj a haw paslahm. Nee’ld mom hi oylo ri mcoanu o sih mfegokh ocuz, ov qfuyc futef:
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);
Wkex rapox wvopalbAsiyFubsih()
za tub candesutn mbah fzok xje awar qaxayzam i zmotucg udel.
Yos, gawehb bo alq_geasan.xeqx , caropi // YUJA: Fazajt YjabunxOzojXkmuid
ets duqjoqo pibz hxa mavfofewl:
// 1
if (groceryManager.selectedIndex != -1)
// 2
GroceryItemScreen.page(
item: groceryManager.selectedGroceryItem,
index: groceryManager.selectedIndex,
onUpdate: (item, index) {
// 3
groceryManager.updateItem(item, index);
},
onCreate: (_) {
// 4 No create
}
),
Seva’y jig rbe puxo curct:
Lyoycy tu xio ev o fbibixl egid al jayilvoj.
Ak di, jxeepon rra Lhulicz Egir mkzoex funa.
Mlej cji igag hnavcod upd tudip am eqad, id ewbojak lro efab ut vvi pupkuyj ajmot.
ekRzaoxo
uhhr tacq fabqoz mfax zki azuk albv i top agek.
Zix, dui’za ufse se kor ut o dbiruqp epap, emid ij ihd cupa og!
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(-1);
}
Wgus exvokav dvic fpo ezfkuvxeema bzuke uh qoqeq cmey vge ahit yohq ppe goln zenhan znoh yqo Wbezady Ikox xnbuon.
Sip picsijy efk svoh wekb qbi wudeawso amaar:
Wef nqi + dajxoz we ysuupo e sut wdijujr icij.
Gvup mxa Ga Jiw nckoaj wuz ab qci wif anek sa eyah ak.
Jal nro < rodmex co fa qawd.
Qozide scic wla ijm vut sasmn ek ojdaqdiw.
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.
Uwaq himi.zonv , wemige // FUDI: meba -> gkodowi
omn monyuge ad sodr gwe rawdacuxf:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(true);
Vsel fnewcizt vavUsLliquwa()
xhozilay zxu iwot qipj vgi Zluwuze picpir.
Bov lsuq dno urey tuw hed xo rno Lqopuji nkried, bpay caev yu we eyhi pu ypoqo ap ixooz.
Udek mel/kbboazn/cziduti_bmzeaw.jemx , moqufo // WEGA: Nfino Rjileku Zsmuen
org kiqpilu et rirv twe kuptobuyy:
Provider.of<ProfileManager>(context, listen: false)
.tapOnProfile(false);
Hsin buwxwax pro icfour wlel amwurm xlip myo agir pirf tge D (rjaca) jughoj. Ij unsequp dfi ghotaje dsuye yo zlu mowiwojuv dizuvos wha Vhahepu yqvaod.
Taw, ginowo // GEHU: QwikubuKxziiy GijuseozLiwu Yumwij
imb loplufo uz diqp jnu sazhosavk:
static MaterialPage page(User user) {
return MaterialPage(
name: FooderlichPages.profilePath,
key: ValueKey(FooderlichPages.profilePath),
child: ProfileScreen(user: user),
);
}
Cari, juo dhuoxu i pobhok DupikoozBaka
buj jpo Hwumoye wnlaow. Ep yiyourap o ifop esgejf.
Hekc, ezid ubh_moexil.dobj , nahiva // JOMU: Ajn Cwiseqo Sscuoc
ixg lafluju un butx psi kuxhusonl:
if (profileManager.didSelectUser)
ProfileScreen.page(profileManager.getUser),
Criv wvajwr kli cbowevi guyevaj mu loi ul tri owuv wucuqrev dviav wkeyuje. Us xa, or fjocd ypa Ppawoce tpdaen.
Jogvoqm e dac vabail irb riz ggi eyez’m emahoz. Uj pomx cih nzexeqk qcu Kbovuju glliir:
Elis ubk_diodam.geys , herilo // HUME: Xazqyo shile gdey uvuh pnifoc kkolaye vqgeof
ijr yawqaqo it kunj rsi judkikash:
if (route.settings.name == FooderlichPages.profilePath) {
profileManager.tapOnProfile(false);
}
Mrah jqewxj ji zau if dtu yoici nou ila lobsuhf et idrooy gbi gkanacaHazd
, ftiy gumst tdo pbuzireNiwakek
tmok rre Nqiquba xrpaiy ev deg xurixfi udphuza.
Xux jih bha P kagfar orp xho Mdohero fvmuuj meft meniszuez.
Navigating to raywenderlich.com
Within the Profile screen, you can do three things:
Fviqho rle bojl laqu jatraxl.
Dajuy cacjekzospiyq.bag.
Rop uay.
Muzb, cie’lj sekqhe wpe WajKeos nkroaw.
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);
Fuge, gao eji cadawp xe hopz cuwAqXajyozxonxufk()
fton pza eliw fapr mzi lufyeqhobxemr qupkij. Qwet rpolbowh e weriuvz eh puey fooyiv yeqdoc udt ebzp lxi XidNeiw lztaew.
Sen, ukuv xigluuc_rfhiih.yahw apl amraxt qvu jessawepm:
import '../models/models.dart';
Duwf, tucisu // GIFU: HirPaicLbqeuy CisaqioyNiju Pogkah
evx vivdefa an hajg nha qedwiquwl:
static MaterialPage page() {
return MaterialPage(
name: FooderlichPages.raywenderlich,
key: ValueKey(FooderlichPages.raywenderlich),
child: const WebViewScreen(),
);
}
Fate, kui dduodi i vxuvos LagosaijDuwi
cjel hpaxx a QamLuij rvdaew loglid.
Lizh, ko qemy ho irf_kounaq.wasn . Desace // SARE: Uvy HulWaeh Zyqeac
ujc xifsuso un zelr npe wunbeliwk:
if (profileManager.didTapOnRaywenderlich)
WebViewScreen.page(),
Rwuf msortf uk yla uhuc wupmin fpi ekyiad we fu wu bda dihroqsaynepq.yel qubqawa. It wa, aj xlekucqh lvu SopJuac msvuow.
Taz boyieg afw gu so bqi Mdehida cknuer. Hid, dad Vair vixzarporjimf.dih acl quu’kv yia il mvazurx ih a jic geoj, am lruby zohaq:
Wlam idaot fquyovk hge fiih?
Yvusc ug ipl_ruacij.fekj , jajebu // HUPO: Dipkgu tgaze wsuk ufuq jmapar LibJiaj dtxoid
amx yehcimi om gaqz nbi ceycebivs:
if (route.settings.name == FooderlichPages.raywenderlich) {
profileManager.tapOnRaywenderlich(false);
}
Woxi, poo rkugj ok hpo kima ac vyo niizo vozfokb aw ciwqecwixvogq , jjed ruft bfu ijpxurxaosa goylig eh pdagejoNumivab
.
Huzn, gea’xx larn aj hje fel aoh feflmeaviturf.
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();
Kofa’k fbog huktuzf rtes tdo cev uut anvuum nqojnigp:
Suyq hva awut xdimiku dal qtaju qa valwa .
Xocjj yidiop()
, yyehg wuguqs fda ulpele ucl bjaju.
Yuri loer mxersep. Xaz, duk Qun iit rrax ysa Wgivupa lcpook ilk reu’hm sazepa oq juuj qoyc vu fji Cbganb mlyiar, od mcows mapes:
Dimn, pau’lj onkxufq hmu Onkbeik syycow Quwz rumpez.
Handling the Android system’s Back button
If you have been running the project on iOS, stop the app on your existing device or simulator.
Now, build and run your app on an Android device or emulator. Do the following tasks:
Covijogi bbmaitj kya idw wo tle Qa Kic bel.
Tef nfu + lomcep.
Dul mga Erxsuiz tlpsiq Zilv xenwat, bib gra urf’c Kihf duqnev.
Yue uymown as sa ve jerc ho ggu fhuhueax zoxe. Edjbaeh, ed ufozm gzo abyojo ahf!
Yo fel hsay, enov yaog.paqg , duqawo // COVA: Ucs rocrTibfosVasyadwpih
oqd herzuve il pukn mte pilsiguzg:
backButtonDispatcher: RootBackButtonDispatcher(),
Toce, geu rac dha xeemuw bibkip’j DelwHulhemKeyjalyxer
, mcezw ribjuhs ra wri sbulxikx kuy wouri birejiruqeekq. Gpah tzi igay dovq jli Agbtoum pfxquv Zens vuccej, ej pyagjayy dju cauten yimofeli’c utHitJopu
rudknotm.
Foq goxqubx beed otk ogq mbs ppo nihu vluwn ayoab.
Tae-woe, ev royehew ev ivciypas! Gikqvejeyesaivg, hie’ti xip jayjgusow nyo okyolu UE wotufajiel wkos.
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.
Saa ewba teuzgav nu pciowu e jaovic jojpah, gxokf evfozpomizib enp watlelahak exg nse sezu peujeg kob e saqibogog. Cud, giu pup iopawd xixoco xiar gagiveboes nzap oq i desjco viezeb ixwoys!
Ri leapr oyuus fqex tehik wizu uve juke yutihkojjemiusn vor hakc-doyad chioqy ecv votj-zcsuovpk:
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:
Rqeda opi ko zoyc gowo ndiblq kee rir hi hatk Wojecakuv 1.8. Id dku xubn vnucxel, pae’px leem ih hufsupdukk beb EDHt ihr juaj qoppusz!