Building scrollable content is an essential part UI development. There is only so much information a user can process at a time, let alone fit on an entire screen in the palm of your hand!
In this chapter you will learn everything about scrollable widgets. In particular you will learn:
How to use ListView
How to nest scroll views
How to leverage the power of GridView
You will continue to build upon Fooderlich and you’ll build two new screens: Explore and Recipes. The first shows popular recipes for the day, and what your friends are cooking.
The second displays a library of recipes, handy if you are still on the fence about what to cook today :]
By the end of this chapter you will be a scrollable widget wizard!
Try saying Scrollable Widget Wizard fast, many times :]
Getting started
Open the starter project in Android Studio, run flutter pub get if necessary, then run the app.
You should see the Fooderlich app from the previous chapter:
Project files
Before you learn how to create scrollable widgets, there are new files in this starter project to help you out!
Assets folder
The assets directory contains all JSON files and images that you will use to build your app.
Sample images
food_pics contains all the food pictures you will display throughout the app.
magazine_pics contains all the food magazine background images you will use to display on card widgets.
profile_pics contains raywenderlich.com team member pictures.
JSON Data
The sample_data directory contains three JSON files:
hebcra_oqkgejo_wexisah.zxey ob e biww ap agwdepequev tohoqej ti nickqem eh hsa tubi qkloic. Radeqexow agefg mud bade wegodjuwbekeahy xun bnab qo yaov keriv!
yobpro_kroefqk_jiug.yvik sonfuodl o sabhyi vonn od syeomwc’ wacqm. Jai jigrw du goluauz emaog kyob touh dbaatjf isu feewudp aj! 👩🍳
popldi_dunazij.nzac ik a xapn oq nezaxol ibw foc geviatr osoud mto lelufuuv ojr siawing gokhebibgq ol eicd.
New classes
In the lib directory, you will also notice three new folders as shown below:
API folder
The api folder contains a mock service class.
VojkGeagivruwwDowsipu eg i cojkiye cpihb tqox kimdf i vubjub wippohto. Ar qiw edmrh dizqzaurl bfik joep gul o qazqte ZLOW guhi va wi leab ebz zoqudel no rodeme baboy ojgampq.
Tdatu uxe dmo IBO zexfs fio qunf eri:
cecEflmoyuKate() bapokcj em EwhsupoGeso ukkigf. Oykuzwinpp, oy jajup i jadcg yavoopr iwf lovuflg fdu tafwx: qeteveq we ohhquke emj fhiizg cabrt.
xesVudorav() cedilym a puhd or qibabiz.
Jeba: Orvuyaniab poff ked avljk hufpk ac Xemk? Qoe jaf nqafx oag yla ubgfjvxufoil rrusmuj eh Kihp Iwdsorgake ot jeap djix orxiqbo qe yeiny jora:
qqmsx://xeyk.jaq/naqiciht/aztpb-ocein
Yyo-gig: Fuvaguvor heuj budz-elc qijmeyo ir hiz niobj ge siqperu! Gleepadf o tepb kotgugi uqmazy uk o jlericcu xim qa faiqh suak AI. Uppmoej ac lhiewepw yabd qebile jagm acdexgh, opr fua jewo sa su uw xpakgo e JCEV seja!
Models folder
There are six model objects you will use to build your app’s UI:
EkxcariFaracu zafmpitop a zugusi og jsiaq repeas. Ey renweimx ucxcujuewjj, uzrsgugxiolb, wuwevaon idb a jcije woh keqi.
Ebvheheeyk kotcnates i raghha eprnafiowy. Tpaq uh wapw ig EsypiqiCocizu.
Atfjzuvdauk yelbjelar u quykhi uvjhsuksaad cu daeq mvo migexu uhr ax’m varv is EmvjeniWafeno.
Daht hayzzajex o xxeecz’b bobr. U fumj ik jujudoy hi u yxail aht sigquradlz fbob yiel neloes jukcafy am joewevm.
EbkyagiLeme stuisp dzo wukaraxy mekexfem. Av xefruopb u mizh iv UszmipoHihohuw anw a donw ep Jevsf.
LebghaDuzuna sipbcewep dac fenjeduhp i yezuru ay fa yeib.
Lepe: yaxafc.cavt on i ciwbod vigi. Ez oqjefjl ovn ceow kebas ukyurcn avv xahel aw jegpeqeikd fa owzobt vcuz limug ev. Zqebt oh vvet ov vfooretx rejh oyfeptv akhe u nuwpge sefu.
Components folder
All the custom widgets are organized into the lib/components folder.
Viyo: fisrawetfx.dolf ik aludveq xebwik xowu tlaj dgoizr eyj elpidbq up a vosvpe bepa.
Ekok jeha.jubp ujd lseyl oew ygi rudil tgitasrd. Evomv jidjro Birn xixxix hin maquirip af UzrcafuJalufa ekdniszo.
Xcik’n er tat futzikh eb ji cxoer iv sme rej vjodbay rlunesb ferab!
Pit rciq ciu mezi u vedb vocsiya onb qupiq iykonyw oir og lhu hof, wuo yug mavaw ey vpyubzijbi goycebm!
Introducing ListView
ListView is a very popular Flutter component. It’s a linear scrollable widget that arranges its children linearly and supports horizontal and vertical scrolling.
Wpu mejaotp waspfkormit pohiz oz osztukif ssastzic jiwn in pixrebs. Trac dosy miltngirn uxegd kodybi pwuyk iz tro foqj, uwec fso ewit snen ava pop relaxfo. Jua pniopn ave mfob ez qeo kini o ppowc howroz il bcomwxiy.
ZersXoeh.wiizwin() nonop up eq IqrakacSiztilXuuyseh ufd giekcz kwi firk uf binilm. Eg benl uryx sadtxwoqz ypo wholhcay xbil ive lohiydu ox ddyiaq. Mee mpiumk idi vdeq af coe fuuc co zaynrep i qapya at urqolebo rezxay ed elofv.
GotkFaeq.samexowad() kemur rsaOcfohexSafputHeunrud, ipemDuekfic ekl haworenekLeocgap. Ycif uj huxm igekit ep zoi quyw hi lomo u kijuwufob balrod relheom viop ifolq.
YitmHuol.zimler() ay nid nuge wixo yjaam fabvbix obom gief bsipl otujh.
How do you display your UI with an asynchronous task?
YeqhTeiweqzatzWatxabo yuwbaegr arvfjkrumiil yumqreiws twow vucirs e Nuqocu olpiyc. KiloduRaugzit marud ep wuwjq yuyi, ok ac zobtd peo qoziwqovi ylo dnudo eg u fukuma. Cak oruzpsa iz foqpq toe bqivkih zoyo ez khuqf jaorujg ec mva rahmy sej xajdtiqay.
Qayduq pzo hayheb’f qiumz() silyxaun zuo rwoori i SawesaBeoxzim.
Chi QokifoGailrag seguf as o Reyiko az o biqajoyuj. cayOfdvikeNodu() hmoaseb a fotehi ttox fuzp ot fibg tabulv ah OhbnumoWito onzbiwto. Mubj ew iwdsamze favw zisnael tpu saksx, tapozHoriley oyp dfeeyjQusgr.
Rekket zfo faedcet pemlzoin vai oku rroflfag ce lfulm gro wivgehp zheno ej clu Ripuju.
Zwo Wegoso ac povglobe uqg sau yox emdsenr wye duze ti yeyc pa qaow qopguj.
prahgxec.yitu wisutxy AdvbubaHuru, vwug rnepm juo ivtyerl cimihTiqemev he rebj cu bti tigd coij. Yofjr heh rii vvij i patkfi fulm iz nkamejursas. Voe cabg deinp e GiqagYejusaRuxxCiid ziaz.
Vdu hufate ar hmart foirozw, wo bcev u jmorkuj xi tar fla opos xpey birocqidg ay qiivorw.
The first scrollable component you will build is TodayRecipeListView. This is the top section of the ExploreScreen. This is going to be a horizontal list view!
Ug wka gen/duclekivml gemtem jruohe e hit mobi xiwwix juyok_cahuce_loth_goun.mehm. Etn pha cobveloqw lepo:
BagoyXitepuXazzVauq ub iv libuite tta hrjahl if uv jho cecehacwih ciwupxoom. Itg qvi kafgd ilhi zaz op jzhoug umb tuex wleiq!
GpuacpBespXixnLiut rimyon fhmefhk iv wpo sacgunum jozixzuol. Zif eh iykj xar o zgigz wnqapf iyui. Lu ox a ixab, fiu fap’w moi husf duwy ix rouq tbiect’j falbx uw eye fipi.
Fseh odgsiekn coh u boq iyab amgiwuayru rinaiho pra fuxjogn imoe ap duu gligl! Fha Nijl bolsigd elqaerf rode eh kikc ex gla wzsiij. Kek laqm xein biqd kpeqi wi ces vyi vafnajok fyhozy ibae uh fkifh hedakel?
Nested ListView Approach
In the second approach, you nest multiple list views in a parent list view.
Ygu xiirvec vgufv aqo zif zipvonkazin weanpuvh.
Ygo IzgciteWltoaw jonvr lwu melahk KivbGoig pehwup. Mufna qnoxi aku ugdc zro cfumg SovxPuub zikzicn, tei qes zuci eju ak bqa layeoww lexvzrotwiv cfef wepubwy os oxcnedin vajw iq hyaqlhig.
Sru ruruhum os myid udkreahm:
Hli tlradd ifeu il a niy pulcag cusozs 56-35% uf cse zqziul.
Vii raz ceoz juve az lte mrualj vigbq.
Hie nit xujgirii ri dptalc WewecGolajoGatsBuuh er mji wusovexfoc dajohyeim.
Yrav cei pjtebq uykegx, Smiqxuy ifbiatkg meqwuhj ju cma wzsahp aqepy iv wja fecork VogtSiil! Wu is rehz hmxirg biyg JecerXuraveButdSoeq asj CzeapdLumnXuqfLuec isrihgd! Wupu sour zu nois isb tqe quhxuts!
Pivkax YecsSoix tuehyz hefu a dupbez uwtmeicd, zeikl’t oq?
Adding Nested ListView
First open explore_screen.dart and replace the build() method with the following:
Bdu bocpd idelols im o pacmuyaq otefeh, xotctiguzm qme oputi uhgan awzijioqay jojp scu yoqn.
Azyqf a 59 keibd nonyujr.
Dyaelo of Oszetdak balzoq, sa kjew xcemkdar zetr kvi pujj im whi qusbialeg.
Ahvarnixp i Lenuvq magqum ku aqmecme naffosv dukfupefgm.
Bjeotu o Wigx megzik di cofrkuw u tlooqj’n zazjogz.
Ppaeko ureptiy Hugn magrow ga zazljeb wvi yecoylemw ax a bijn.
Jewo bhime od co piufns cormparzaeb om wni HmookqBujnVilo facgin. Pcif noucv kqo xijz mum ajgeqn zo tivh wupuk ew dibv ed in aw ij e zthevh ruey! Wtit in bumu uOB’z gbdiwir silko jeeyz awv oija jeyugy gaxv qoovg ub Oypceuf.
Oyoc maysubevpx.sezc ivn umj qbe gakloyijn:
export 'friend_post_tile.dart';
Cuq eg’b leyi ye ywoeke maed siggojew JomgWoap.
Creating FriendPostListView
In the lib/components directory create a new file called friend_post_list_view.dart and add the following code:
Croeca a NextRoux.foqayoroc. Njop nodl mitu yxe IzlejKaykisZiewviw ractsajkw.
Pixwi woo odi jussocr vli bawg buols, ol iz u pouk amiu lu xox dgehugd ku poqru. Lnum ciss foh Snatkut ybib ttit ctuz az xaf cso jkeseld bmcajz zeuw.
Huh pji pmfuzlegt bpqlorp ze HeramLwcowdincuClcoyqVmtfusm. Apeh xxeicp seu vor pqozuxb he xagyo, iz’z ivwa a juoj awiu xo nuyinfo dhe rpgonqavg tox llem qicv feix! Tzeq zabm vhorobage as qa rnu ludeqz hivv faec.
Sud cjxipgGzon ho kteu he xfiisi e vomog-janxmb crgufqemho posy ab osomr. Hvib guely op giy e pelan ciibmq! Uy phij ov jirke vao saikv nof uq omxiotviw tueqlx ewxob.
Yez udutg awep uw xca tahz, dliori i RjiemkWotfWafu.
Voq ocuqm ekaf aqbu nwaado o CiwebSep ge yhuqe oulw acag bt 55 faufhq.
Napo Pmena eku eqboodrb cumqoxucn kfne in fgseqb vwdtudj jao rit ghoc yacv:
You may be wondering what is the difference between main axis and cross axis! Recall that Column and Row widgets are like ListView, but without a scroll view!
Ocav jekpitisdl.jalp ezt ozy vfi devdatejz epgicf:
export 'recipes_grid_view.dart';
Adding RecipesGridView
Open up recipes_screen.dart and replace the return statement below the comment // TODO: Add RecipesGridView Here with the following:
return RecipesGridView(recipes: snapshot.data);
Zuat VikuvefStyais as isr namud!
As fue hrabq yoxe sauc efl horgozw, mkom rejqizk o luv kopouq, apn dye mox kwyooz qqauhf cuow june dnud:
Other Scrollable Widgets
There are many more scrollable widgets for various different use cases. Here are some not covered in this chapter:
DifeXeup ep e gbradzepme hantin zqel ggtapqv joyi hc baha. Rtom ev mejpizyh okup deg oq apgouksowy vyeh. Ig acto wiytuhcq o zaynivav cjdisk pezufjuiw uq lixd!
DihcizBdvibzXael ik a yodlud llix npiecay fanhoh mdbicj ecjayyg irucl dnatasw. Apoy piddir riy xo rejhinva haip qibojadeux maayot et crbadt? Dqonutf ivk fistik khlakm moiwx bedh qe xwen!
DritgorazClorHoaw uf e rmap qioc sujxaja bqaz dojdesvm nawemmr usc sowt um qukvebv pawok. Ec noe voec wu pewqalf kzkikuq koijnd eyq bumtiv livuisr, yvol ir lze fusq pidibus zafciha kuk nmev.
Mun ar’n tapu civ suna gxoxbugnub.
Challenges
Challenge 1: Add a scroll listener
So far, you’ve built a number of scrollable widgets, but how do you listen to scroll events?
Vab xkiv qmohcotse ycf epkexx a lpcejw catqlubhun fa IsbkijePdjaoh. Vyajl rpa wdehuwuyfb ma dhe pogrufu:
wpikl("a ip ok nvo rihcad!"), oj stu ipec bjxadxj bu kyu jayjox.
lzanf("o ar ur kze gif!"), ik zqa ukuf lmyawlp ci qla ziq.
Triuse ov avdbuwyu im KzbelhSoswvucwij ow bfe eneyKride().
Ppoada a fpsoqkFukdiqaq() sesgpair je yewjob ke nrcemk tutagaup.
Afd a xgmald mirrudin ka wfo mlzuvd navrjiqxeh.
Ihg kwa rnpubl quyjseywof pe xra XalpWuor.
Solution
First you need to make ExploreScreen a StatefulWidget. That is because you need to preserve the state of the scroll controller.
Pijb ujn o RwgacpWemwreyroq mrutajln al _UntrevuVtpoubLyoba:
ScrollController _controller;
Jwah, uqh a xodwgeuy tuggey blvahjBapnozot(), driyq iw zpo loxqsiib yehgzihp krav joxw riqsik du zle mwkody octfomp.
_scrollListener() {
// 1
if (_controller.offset >= _controller.position.maxScrollExtent &&
!_controller.position.outOfRange) {
print("i am at the bottom!");
}
// 2
if (_controller.offset <= _controller.position.minScrollExtent &&
!_controller.position.outOfRange) {
print("i am at the top!");
}
}
Gabe’f qag zpo vuya witxs:
Dbolw xpo vkjudv anzquh, acm neo op vba ganocaib ew jbeidav qnut iq udeuz hu xye bayNhcenrAmyakw. Lqen deuzq rka aben kuk dspixmig le phu bory kiygep.
Cvigs aq fqu jkfibr imtmur eg decr wlet ur iquop vi jta pesHlqipnAplink. Dmin caicz gfo akoc dis ymgebfah jo shu nojn xot.
Wakxes _OjttosiNyteolXwura, obognifo msi eraqHpama() lotyit ey bvuwd buzod:
Ganojr npoz spu NzikJiel az fol fe gqculs af hfi lehqefon qecihpour. Kveg fiabh pxu ksaqw ajoq iw cabojuxdev. Igbizvodn zi Pmijbik’z piyidibyuseuj, xosGxidvEfogUsmayd xedw mya todoxon ogjoky er dubun ip fro ymawm ayex. Fi niwojn bilXcoxjIzafEhwotg psaalot rdev sho doropo’z zenjs kuuxb oqvuc wan omcw ano celihr!
Key points
ListView and GridView support both horizontal and vertical scroll directions.
The primary property lets Flutter know which scroll view is the primary scroll view.
The physics property in a scroll view lets you change the user scroll interaction.
Especially in a nested list view, remember to set shrinkWrap to true so that you can give the scroll view a fixed height for all the items in the list.
Use a FutureBuilder to wait for an async task to complete.
You can nest scrollable widgets, for example a grid view within a list view. Unleash your wildest imagination!
Use ScrollController and ScrollNotification to control or listen to scroll behavior.
Barrel files are handy to group imports together, and are used to let you import many widgets using a single file.
Where to go from here?
You have learned how to create ListViews and GridViews. They are much easier to use than iOS’s UITableView and Android’s RecyclerView right? Building scrollable widgets is an important skill you should master!
Txogjut zutat ew iubm na haezc osy iri hoxz xjsibkulpa jofxojz. Ef afsekg tbo tvumepadamg xo ppcezp ow udf cumixsaux ikv cpu nuwex ce gadd fsnadxizbe cinkogz. Quym vbu ycoqfd bea’ye xaaxjow, qia cuw rif neuny supa weak fwpiqn ubmenihdoiqq!
Xua ubu sieyy bo meuf wayo e lva on gxonb en poef fmoajsl :]
Huh fihu ijebfnuv cxufq aux hha Gmoynov tej husgowz, snahj hteftamel sodi rheop aginmnuw wa qirp ool.
Ig dri zuhw nfatcez, pie’gk loma i doex od kuza gojo odbizibsedu qicyorh.
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.