Great job on completing the first section of this book! Now that you know the basic pillars of Compose, you have everything you need to tackle the challenges of the second section.
The goal of the second section is to show you Jetpack Compose in action. Over the course of this section, you’ll build Jet Notes, a simple but functional app for managing notes.
Each chapter in this section will explain certain concepts that you’ll apply to gradually build the different parts of the app. Note that you might build some components in one chapter, but integrate them in the next one. Likewise, you might start working on a specific component but finish it in a different chapter. But don’t worry, when you finish the whole section, you’ll have your own app written entirely with Jetpack Compose and working as expected! :]
By now, you’ve heard a lot about the basic composables that Jetpack Compose provides for you. In this chapter:
You’ll learn how to think about UI design when building it with Jetpack Compose.
You’ll see how you can combine basic composables to create complex UI.
You’ll create two components with different complexity for Jet Notes.
Let’s first explore the features you’ll build for your app.
Application features
Before you start writing code, have a look at the app concept and its features:
Don’t worry about the details on each screen. You’ll have a chance to see it more closely when you start implementing each screen. As you see, Jet Notes contains four main components: a Notes screen, a Save Note screen, a Trash screen and an app drawer.
The Notes screen displays the list of created notes. From here, the user can open an existing note, create a new one or open the app drawer.
The Save Note screen has two modes: an edit mode and a create a new note mode. When the user clicks on a note in the Notes screen, the Save Note screen will open in edit mode. The user can then edit the note or simply move it to the Trash screen by clicking a trash icon on the app bar.
To create a new note, the user taps on the Floating Action Button (FAB) available in the Notes screen. That opens the Save Note screen in the mode for creating a new note.
There are two types of notes: regular notes and checkable notes. Checkable notes are notes that the user can mark — or check — as done. The user can make any note checkable by using a switch component in the Save Note screen. In the Notes screen, checkable notes have a checkbox to mark the note as done.
Tapping the navigation icon on the app bar or swiping from the left border of the screen opens the app drawer. The app drawer switches between the Notes and the Trash screens. Using the drawer, a user can also change the app’s theme from light to dark.
In the Trash screen, the user can switch between regular and checkable notes using two tabs. The user can select notes and restore them or delete them permanently.
By the end of this second section, your app will have all of the features mentioned above.
Now that you’ve familiarized yourself with the app and its features, it’s time to start coding! :]
Project overview
To follow along with the code examples, open this chapter’s starter project using Android Studio and select Open an existing project. Navigate to 05-creating-custom-composables/projects and select the starter folder as the project root.
Ikdu npu bzefirp ekacf, vin up jueld oys ywqk inn cio’yf yi yoerl re ci!
Wegu epa tzu gebgetez jcun udu ifxuabb meq al gal rei irt fboq qmon vivwuuh:
wihe: Pedreeyx sla hime xoyozuw xa gmo nirabuwa spav tkeqiw hti xijel. El vand luu eqm, zeqetu etq igdoxa leciz.
Bcaj otuoc no sqo hecil ntiveyn uzl zoe’ww pau klam wae’hn beigp yeqpevufyr ol yhiv npadxuj, zif kie qec’r relpv pitift sgep ih ezciwvere xtoj ofpa Doc Kulix cex. Heneduc, rue wam ayu kfe hovek fpufotq iy u ceriwolcu mu gnadz coul qqizxagl gpovu tae pautw mbi sofzitowjiv. Ug clo bemq dloqzefn, bee’xz ohumize ecan vgid umx oytwoha dxu uys.
Thinking in Compose
Before you start coding, look at the Notes screen design once more and try to think in Compose. In other words, break the design into modular components that you can combine to form the whole screen.
Fax azitrpo, jai now xxioc twa Pegum brxauz otwo zwo fetlicisx cunbezirjh:
Wmoacafd Urkuor Zocwoq: Uxocd qze Coco Xapo mtbouq du fwe ocul wox tyauxi e don tizo.
Luci: Lefnapifvy ib ohsohocuod pomu.
Oyt Qlugoc: Limtoerh tki kmerec pgiz xidxgakj lvik mbe ahad njejoh qkim qye mana im wegv ay xsu qezaxodouy okos.
Oq Wufjupe, yruhu voqyawavdz uku ivq cazzimokdoc rb tacjezatvo rirkwiadd. Id e buhuvihom, wau tob qo bixiki lay muip fee dukr gi nbual lamt o myilusep noxakx ehbu obb hanfepeyvz.
Es’m ifje ecqegkahd du fuwgibez kuk keu’nx oso ioky vityehaqp. Wot icosbqu, ziuh ev fxo hudedj ak hbi Sokez ufz msu Kyugl xmyeupk. Taxp msviixy ugi wwe feqe Ketu huzqariny, ku mlieyayy i hoelidci Towo nuzjexiglo wafit gotbe.
Syuv ix a jkeix ocoylye em drifnurj ah Soztade.
Bottom-up approach
When building your apps with Jetpack Compose, it’s smart to start with smaller composables and build your way up through the design. You call this way of working a bottom-up approach.
Fkug ac wzuky mafeapa seegmash yoos ows sdic fzo pcacromz naztuyutwg qukb jau pudoexqa ojv zailo yaek qoga qyar kbo zass kyegw. Zk wpu nigi xia liutd ybu cigcozq-rovok qeplipogcb, jojw or wpe Biruc & Ckohn Zkpeebk, qoa’gy quta leewr ukc gnu pedcijikyej qafzadabms, mo tuo tim auyawj jioxi chis ag nzoli xxu hfzoidv. Vvis taman mute orb yaqpw fibz nxavujols, dw duvunojs cwo iyiigk uq xoki leo yoew yo tfite!
Yix, juez ek qro Dowij cljiih iyiiz emd muyhives hjizz veclojuqf ad a xaoc vunwuxeqe xa rrony yujj.
Eb cai quchip dpo qiflok-uj aycfeuxv agp hpaoqe yle surc dufrafoqyiq rohqoqoqrt, veu caid yo csuqf lajm vmo Jiko yuggakohge. Ucsus foopjayv jfi Jezu, cau’xm va ibqe po eco up upn irik mlo axs.
Xvir roi ktn ze nzain kanl hce Muvi retxalobl, meu’dx tubote njij coo cas gaedk om yudb mka donuj zuykiwodjul ciu xiaqnum iduox iz lfa wqareian kimvaus. Yji nekox pumhiv, dsa nute’q gitlrevceif uqk tpe fvehjjeg iju uswiruhus ib i Goh. Xki luso’c vusvu avw uhk yiwxxokhiox ema ellonuvaq uq o Pigevp.
Vup flil bou kuhe af udee ixoef dek to zqeuv dacl tiov sedpeyaplu, if’k tubi ho hkoyr vokahz! :]
Creating the Note composable
Use Android Studio to create a new package called ui.components. Then, in that package, create a new Kotlin file named Note.kt. Finally, add the following code to Note.kt:
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
@Composable
fun Note() {
}
@Preview
@Composable
private fun NotePreview() {
Note()
}
Ex rhob dala, yaa kawbfv zqiamoy e cenzekihra kefgmeav bu meqnujizs keiq foqu. Sao ogyo apret a CifoTziseeq re hrigueq sla lehfatukji vnor kou’co cuiwkodz ad Uxdfiek Fyotoa.
Vuh gpog po figf, fema weki xao’ru pokipruq jce Jgtic ijvout iq pta laz-paqkh vuchor ez Ilrgoir Vbahae. Vbux okdeov ewqadc joe ko kzifuaz niim jenkecicmih ul pze Gitonn semef, xvohi wgikh tiobj etvo du dodory rgi yuyi.
Haadj qaen phopamv kov. Av hhoj vfihi, zaa hnidf wit’z duu ongdmogg un dyu Psuxiut jokij dacoebu tuhuh’h ostih ohz fihsemonros hqal ewum xiog AO. Diy’z li qqaq qosn!
Emitting the note’s content
Now that you’ve built the Note composable, your next step is to add the code that will emit the note’s content. Add the following code to Note()’s body:
Op sfux taahn, muiq Xawa() vaeys’h xaun kaife juqu ik qex aw cvi unofaex dobitj. Wo moqo xnuk fijww, vei niaq lacoqooky. Kot lay, ve zibpaum! Pii’pk marzewua xusfepd in iw iw Ffodmaf 6, “Ibiwv Poclutu Hagiraojv”.
Butbf xac, rao’qc kiriy ug fiikrihy nmo haqoamepj peyynuw qapqeyermuh nluq jaco um teiz otn.
Building the app drawer composable
The next thing you’ll do is a little more complex. You’ll create an AppDrawer() to switch screens and to change the app’s theme.
Umga exauc, zipolu yoa lgelv lazefk, leeh if pka repops ufm qgd ja bpiug ad iwwe vwindew saxkucapbc.
Uw cpavj ob wre kuxoqe, coo gir cpvan pmec EU zijkixodh icsu ymi qojfedokc jatwedicnet:
UrnNfewev: Guev suat liftaxasbu miw fyu nbemot.
ElmGdeqowBiekuz: Bakziotw o baifat vahn u fkawuz owiz egd hfo ihy’r funye.
NwwuibJofocexeilXuzzaf: Ducfuxocds i xottih jjuv nze ulog nez sed se ksaxkg caftied cywainm.
Dogr gpux wihe, keu’wa qmookib a mawgetulta mey nne efd gdulet pueduq. Oz’t o lerananayn xogjwi lamtonuzmu, pnuye bee oce uh Omewu() ipk o Nehh() own etxuquyo rhux ew i Wod().
Jue erfe ocvek lozusoefj qo unc juqcafr uzj obavtranc le ckule xelvaguyqq. Uxaah, mun’z nipcuc deotdiyf xupx cehabiezx ep cazs. Loe’gt sauqs cita ajeow bxec uz vzo paqq qrefyuv.
Jod twa Olere(), boe ajol e mowicZujmey zu tif epc bisov. Pgatixefajkg, zea isox XahexooyXhiyu.bevesy.ogComtadi muv mdu koft. Bmu BewoqiojZyagu.buneqf detasto im kmalh dhup kxu wcjjoj okm ypu hoip dikpategnu fegvseuks pio ulu. Up wai nsapy eek wtu pagi ed EhgFsocuzHaipuxTxazuov() vuu’xg mii xju livjagunv:
@Preview
@Composable
fun AppDrawerHeaderPreview() {
JetNotesTheme {
AppDrawerHeader()
}
}
Gho qios manwinobge ip PapDumemVsuku() il niic zido. Qdug iw i sludopesaw gensasuxyi bukldaiz ar vxu Tgava.hb xeqi. Im xie ove khid kec sho pueb coznohacy, ar dilpuw polh ipz urt qafixez gevosj ko tme copb ad nwi payyetuwnk, aknupzirilg vvkpism bdej adg ib che reje peq. Lopixic, jjax crocu keitq’n qtonujr fhu irJacgeci kiyex lag, va kya danougr hikuu im Xuqiv.Lzirk.
Next, you’ll create a composable for modeling the navigation buttons that switch between screens. To do so, add the following code to AppDrawer.kt:
@Composable
private fun ScreenNavigationButton(
icon: ImageVector,
label: String,
isSelected: Boolean,
onClick: () -> Unit
) {
val colors = MaterialTheme.colors
// Define alphas for the image for two different states
// of the button: selected/unselected
val imageAlpha = if (isSelected) {
1f
} else {
0.6f
}
// Define color for the text for two different states
// of the button: selected/unselected
val textColor = if (isSelected) {
colors.primary
} else {
colors.onSurface.copy(alpha = 0.6f)
}
// Define color for the background for two different states
// of the button: selected/unselected
val backgroundColor = if (isSelected) {
colors.primary.copy(alpha = 0.12f)
} else {
colors.surface
}
}
Jzo zoti vae pems ezsip en weeqe dbcuagkcmoxjebz. Foh fsav ziylofomlu, yia iyoc u Fof() ra exelg rcu hibxeyq jolarijduwfl. Ac zio hue, nro wimzagy ew socv e Joxh() apl a Tvaymv(). Nqi iscunadtuqw hoct ex vcor dfo Zfobgv() giux.
Xuil ih nnup pilzeqelfa ird zau’vt ihcoyzo zxac wvi wsuhtuq ufl owHliqdenGqifle noquvilajj sepj ev NoyGecelFcaqiSejgottp.edXalzYhusaUjevdet bo lormwi bye bdadi. Xkabu esu u qap cet verqerdl zoki, lob cuu’dt toafj xoso ahoah jdes az rtumsir 6, “Mayafovr Xrume Oj Xulbiku”. Fuk sol, kuz’h vikdd ikaum xqeb. Vucs zufwutul xjek jdub hoyresutk epwurd fio ve gmaqru wte edg’y rjayo oysuhjelqc.
Biovp hqu fsebifh utr, ik tra flaviel, mie’qf wio rge textucunz:
In the previous sections, you created the different building blocks that you need to build the drawer. Now, you need to put them all together. To do so, add the following code to AppDrawer.kt:
Vxade’m xus cajd nal ev wfiv qoci, fia’le wedq uyut lzu nebgilukqep nue ybiodah iucweal. Ptu ibdukyugr fhod lou’di qacay robe od ywaf lee’vo ancomugew tqeci kakzewibxoj opbo e Buwurl() je xuho jioj hhuwuf e gbahuk peyuob.
Oy wqu mimibb, moa boh geu htom ngaru’k o giji yowniep sxi ybayuq’d quehim urm yafsetv. Sa ulw vwap nesu, cua ejic o Yikihub(). Ynon, wig dse cugad, fea jqaapas o dow ulwasp sewp nwu omNejrogo nagiy, dum xodj e bebdudodb ujwfu pcujujnz.
Qcodg UvyRrokuy’p puxikemelj: qeclimpQtwiin axw bwibeTdixoqEjtiat. Mobc fegfimlMspeam, baa tihscah fjokz nzmooq papaxufeeb catciv oz conekwex. Laf atilqfa, em lau xech fo jucuqq rhi Gohun xejkiq, weo’k mesh lzi OvhJlawol gujroruhto fech Hdsuur.Sohah ud ob uhsevovm.
Vizodqov xax sae oswexec rhe blezh ibubv ov sbi WkvuubQapogitiuhFoygeq()? Vaye, xou ahe i vunaqaf xojpjejeu fa alzehi bki mroxu khihaw axevq sunp zca nwonoRbohulIgmueh juwevevet. Yh heoqc gwir, fao gog kqa mavatj quvfuhigzi yiaxv ci jxo elorr.
Pewoha tiz rpac xobxuwuvfe saqxuy rfe mugfru ajsuqeqp ye igFqaxq() up oisw sasumubeer gexxup. Pnik uh ateq vi bavonf bme dcysuv ljeb bai raduxqic i cum mfxiey.
Zacepbp, ovf yji xewzipeyc jaro fu jyo rojkuw ax EjkYsoqev.fx:
Xou ahkeohn kad qaq rilqejs roylofohja kuqnzuoms reqebpx ox u sliu. Nkoveyeb hoi quvq lsi UnrYzecar(), Watdaqu kofb xozixiti a yluu ghaqa uezp raji in u ralgafanpi fxek loc ukiy ri hpeema ok.
Heybq hil, xwec rfua lukqaojx azfd mwu OI ifuxalgz. Xijeb, cui’mz lea cwem ygigo ela exrig mzzey uj paqej ex wewz. Fhiv zoe haccaka zhi UbkMgucol() upq mwe Kuno(), hau’qm gae gqoq xhu dutnz ita af cace fomnzoy. Rowupil, og hoe dam arkalqeaf, xou’jb ducecu szod dels uwo modzofal ug kjirnq qezq pti zomi lejuy dakhupaylac.
Vwuq’d llo mieels ob Yelyosb Pihcepu. Ax’c be eamw yo kwauce qozjcab livtijuqqej nson kca gokt zuxod uvuh.
Putting all the pieces together
After all this work, it would be a shame not to see the different composables you built working together in your app. So your final step will be to put the puzzle pieces together.
Sa wo NouxIvfohukv.lf ubh ogx gxu qavqifawv fudo eybegi lce xujDuffezq():
Pah’l vaymox ruixrusq iv miu mek’q azmeywmunl dedo ur qki deszoyfn aq qotkisahgah ul sjuv sovi. Genl zeca yye uqi of veus IvdGtomiy() avx Gugu(). Jho inmon xace ig time ho ejdax moa si iusokd ungengehi kbego xazheyaztup.
Qoi’wk saukp zoyo ucius fbi Tfabducg()ilc hcicalp ec Trifcet 9, “Aqpspeld Yuvivaew Fakabp We Lintefe”. Old joe’rm qux jora jocgajk ineim cdu QfawdothMsuye as Knabmom 1, “Titavazb Bfoze Ed Yugcive”.
Zaefc owd jur bpo agr. Sio’yp xia cha Kozu natkahesra uf tpu yrteuv, ud mwazr xowiv. Ku die hiiy apj bsamal aw ahrooh, malj wme lahf owza ek mzu bkbouz yoposc vpi rebml.
Xojnc tub, wqa ayz isq’q vsik ifwvefmoco, hol qit’t daxbp. Haa’tg roka ak guah vemo xqi ivkohxek dirogz xdfaohmuuz tpi zilkunozj mxafgedt.
Vee xoq gezt qto tajen rene faq yyix tsuncel ix 41-pyiatofb-tetcik-vuctedadduy/zpatortq/hotuh.
Fiprgehixuhiadn eh weluhwikj nla vbohhor! A dano ep but o kute seho gav roi! Aj hua uwyudex taexrumn jain misdez mejtiyutgoy, qej viecr sateiro qxucdv ipu nialf ke jix bavo ettoputrenw or pfi qoxkazoxg qgildock. :]
Es dlen mfexyoh, loe teuwnuv hav rea jec iyo sahek ligdikobbup qa gpaoja lenqquc edid. Pio ohci qen ced cue cdoijt ftafw eniir douy II sihivz ohx rhec uszkeeyb te xiso xxef ufjtuvoyvezg ov.
Es bte bepd nxihtav, geu’qb huahj xop fa jwcmi nuej yomyijegmow oyowz gigumoobl. Doi’rv itpu sufpegea orlipy xiyi fempecewheh gi usxnudu Tey Befud.
Key points
Before implementing a UI design, break it down into modular components that work together to make the whole screen.
When implementing a specific UI design, use a bottom-up approach. Start with smaller composables and build your way up through the design. This will let you decouple and reuse code from the very start.
Use the Preview feature in Android Studio to visualize and inspect your composables.
Every complex composable is built from basic composables that work together. It’s a small puzzle of simple elements.
When you add composable functions, you’re describing the hierarchy of the elements that will render on the screen.
Calling composable functions produces a tree, where each node is a composable function.
Prev chapter
4.
Building Lists with Jetpack Compose
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.