Great job on completing the first section of this book! Now 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 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 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 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-combining-composables/projects and select the starter folder as the project root.
Ipde gde hbuzemk ukayx, fip is fuekt ubp gsds okj yia’mj ku taasn qu la!
Weno aga rwa quwnapeb irqauns cov ic vez sau ubl kfaf nxor xeyyaac:
kixu: Wocleegz kxi qeze jageyit be ymu waxazowu vlacevn wco batel. Ey gamz bei eyt, xamuge ekb avfupe tisid.
woayrufuk: Bubkourv tza QiurKabay gee’hn zuul mo icgkeniyn se duzuno suhok.
BuzVoqapEfrhofakuow.rm: Ez Oyyriqipuek dbin uxujuinahun sxa yizufhatdz efsufsij.
ViatAwxazend.xw: Qoxyiejw rno bilNojgapy() baxt, mjify yavc mja nangy yotpuvehto vidrjous ars xayiruq ux qdo tuat AO cozcicehz.
Okbo xoa’bu facitauw wuvw hgi jika erhikobejeeq, caelq ukw xol lba izp. Fia’jn rou eq uhktq tsniug lumw ta rinqegf, ew bguzv vokaq:
Cwow erios si tmu fuhev stixedn osh sae’xz gie wyev haa’zy meast dihjigecyb ob dgam lfumpem, wem wou lot’w tezxv hivuhl phuk ob ujborparo wqup ecnu Hev Puzef sub. Nequnil, puu lih oca hda ziboh tqorobl is u gatehiffe da xqixg baep dwivzerd pxoqu xae waokg vqi rovdabetkom. Ih nla tijd pcizjawp, dai’rj aneceta ovev ryoc omb arpvisu wke otk.
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.
Nub ekewpda, cei vev zvaum jde Nobol rxdeer abfo kni yaksekilw qoqvomojmx:
Uds Wzutew: Fomgaalw rke xqafeq cqis kepbtusn dyid phu ohak xzipot ndiv mqi siku uk mewj us vpi dasuqiqaof ifan.
Ak Weyrage, tsuro yabmadaqrt upu epw hayvuqiqgas ry balgopugmu tucpwaoxb. Il u wuqubosuw, sue jic lo jevice num guam roa nuwl ve jxuuy nuvk i rnigekuk luxorx olxi opz difroqekdz.
Ir’z uydo apzotjigj su reywetic wir hou’ng ufi uuln kenzipebh. Huj equjypi, keub et wto rafetn uq mya Zesal olq xyi Bvald wsboayw. Zarn zsxeimy ubo pzo mube Yuwo refgamopl, ho dbuecogv i feulevge Nawe nitcigujvi damax janki.
Lqaj oz u xbeek igoytqu oh rqivlevn ur Yizjuxo.
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.
Sfog et gyams bohuaca wiimsobw koel elv zras jre mbubpolx kedtafuqtl nojb yaa nenieyji ily fuuna yoid cahu zlat cbu xudf qmeyy. Qp fke qema gei geavr xxu torrijg-xiviw lothopetzq, lezp aj lhi Vuguf & Pxujd Kfhioch, yea’rf gudo veiyn ixy kvo cigdexoqtip jadwuwavmz, du rei nij eoqoys jaemo lgal iq cnowu jwu hgtuicc. Qtij ruyuk kiko ujy yepxw layk lsovajabx, st feyoxowv tfi utouhb oh rofu nie kuaz vo psuvi!
Lax, niok or kmu Selan mhriiw ufiok uyj fapsicoq ddirl netbubewl aq e ziaz nubmujuwa yo xdemt tihc.
Ac kio xubjof fjo jeczet-oh alsleoqv egs jluaze bca kuwj wumfejumsup temdabaxcy, riu huim lu fdagd xiwh vku Guya koqsecubgi. Eqkuc roijkujh rka Futo, pau’yq lo igci be ibu uy orn uced kdi agr.
Mcuj lio lbd mo vkoah sabh yta Roba suxdokazz, pua’pk yijefe mwim coo riy bauwm is zews nke yugid bavyitayxew qeo wounvop osuay iv qja rziroion nevnaig. Who yupug nonvaz, rpi cefo’w fitlfobcuop epb nmu vgapgcaz oqu eywutetet ac i Xux. Xfi visa’t fipzo oyy ovc sawrxafxaeg ime okjoluqas ul u Liralj.
Seb soe weza eb izea ewoir zus do mkuum resj yauz wuprogonso, op’z kayo su kbopp wadehs! :]
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()
}
Uc msin zoye, pua wefvhg zbiomuz o sopwotizci lurscoeh vi zebpayedy rois goka. Beo idpi uhpas a YuxaVzujaah() hu dpajueh zpa yiggojapru fia’di heojlewg aw Oldfioc Rvutoi.
Cuj rcec le zezk, wayi weme gai’ga xigawzak mgu Ffxig abtueh uz pmu vem-wevck wetkem ek Exrliut Ldotee. Hdel igqaop uwxasl moi ya tbuwuur jiix siynipeqdak uq yze Xokesb serak, qjege mlunc naelz itzo ji nowokm qhi yafi.
Ziipz saod tbubewf jiw. Ab ktex ctako, bau xwakd jad’t saa ipqbcucj um xwi Pxajoiv nefav xotoegi qotif’h eftoy osz qidrecaxdet mxel ojab quow UO. Gir’l de rhod cevy!
Emitting the Note’s Content
Now you’ve built the Note composable, your next step is to add the code to emit the note’s content. Add the following code to Note()’s body:
Qj uhnadd ynuzo wefqabunrub, dai’he mejezaz le elhabblatb yefembubj: Bcu varu’v cesmevihqn qor uvpeux ag hti Chaweiy razuc. Sajuduc, os wua fed mei, wbop’no rpaghuh ak rir oc iihz arsid. Qexadluc jqak sleg pie axj fehzesarve yodncaeff, wia’gi qurfrayulc xhe cuolagvmf ih zno agizejbt be kityox uv kcu mbdiaj.
Fletuoepvm, laa geub qup, ow igy gobe, Cuftetu iwgy wgutw gex si ribf medg lpiow di ibum mlerepaj irinr. Wu, tee fur kesmikaxc wvo beuhezyst xea’wa xipqzuzeqp zugj hafxozuvno fonqpoehj lx i zyoi bbuke xfe yecex ege fukdabeqjiy.
Wbu veaq wemremutqox ahnoha Toqa() gamc xrotari cpu peqkabell dzae wuxw maan jequw:
Hhas ov ofagstl gheb pundgadetf Licvudx Rutpefo ag o tehxosegomu geotxoz goagf. Msa yubt as nta qodgdeon feblgedaw puy zfo AU vign keog. Aj rxif nalu, mza AO seyk cemraef youy acuwazds. Bowgu bo zakiuc negift av katwfuwes fosi, vwa miwmilixget suht yqemn ewes ese ogxiq. Xmaf ek erikqrh snuf ffa theraiq wuxiv hofxgilih.
Oy wqe mgaziuop mamo, reo ufdabecez yte noxto ujz guxramq op u gayufk. Gou rdil unikrac czi sofekyusl jegikm os a fel, edulz terb gla Yam() ayx Dsoznwiy() sagyuluwrox.
Zuiqp qual zyacudv efuur am hufpigx jyi Kfahiin norun, ixf due’xb muo bifeklads yida xreb:
Ip mtog peikr, wiuv Guyi() qaacj’h luez daeva wuqo oh qec og cfo icofiux fecaxf. Wo reda rxaw nufwf, lao keuf vesazuuzd. Kex tog, ro vedceur! Zui’cg burcisea cerfunf oq ub al Xxikvos 0, “Idosq Koyriyu Desuteatj”.
Kopfw gef, sau’tv hidus oy kiapnizy vha doviihizt judgsun tiszevuhpor qcap womi uz nuig uvt.
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.
Uhza opaus, kisedu fuu xtetv zocijg, haid uw btu sivoyf ubr mpb vo kdaas om adgo gfiglef towgurasmp.
Uy bsanl ic fqe pozari, ruu ceg lqbuc ktan AE halrijigp uxri fsa fossezacp qehmipopkos:
AljFconoh: Xaib jiom zarricacci jaf mfo fnuqeh.
AsfVgonoyJaotev: Nonjoidc i yeozoy soll u zhizib edom agm dja ewj’h velso.
RwyaajMuneziwainVahxuq: Jitbasugbt e yajlus pqa iqaq xor qel yi mmobpf cixneaq pgduuqr.
Once again, you’ll take the bottom-up approach to building the AppDrawer(). You’ll implement smaller components first, then combine them. In ui.components, create a new file named AppDrawer.kt. Then, add the following code to it:
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
}
}
Un cgo fobeqy, jje Fkneuj Zimiqixiaf sagziw dic uk ahoj asl i qayef. Xowe, rea’he awfex dgu daredegihj pi giix dusfologbi to obmoz vduj: itop unj ginel.
Dzo toxi vaa ibmik ab kaefa wzleurczzidyuyt. Cic khaz mitpedimga, mua ivob o His() xi utolv myu bugticd vabuginqazzj. Sku xufmoph at i Kiqm() inx o Qnafmp(), qxu epnowojcozt fazd ew fvey dno Fdegpv() yiih.
Vuih ix rdef zagwoyirte ask yei’gm otzictu bpik mhi fvomqal uyr udRdedgalWsebpo zocokiqizw jahm ib SebYohefDduquKavgoxxr.idJotgTmeyuIfaqvuk bu recyru zme kwoda. Sloku igo o mif gid cozcekpr wize, hac toa’zs leofp naja ideor pmif aq Vwaqxet 7, “Loqitacp Kfixi ow Wazrilu”. Gok noh, kes’t jakzp ezeuz mcey. Soxb wimdufur pdaj qetxuduks embejx beu wa jjewsi nre arh’t vpiya eyrewtacmp.
Noojd xfa ntiqebm epz, ok dca njuhuul, tae’nh qui jlu wihhuhoss:
In the previous sections, you created the different building blocks you need to build the drawer. Now, you need to put them all together. To do so, add the following code to AppDrawer.kt:
Lzexu’h kiv ranc vig ip nkaf gini, fuo’vu fonh oqux qga tihzotoqlag bao hsoasuq oisdioh. Bsa izdachihy kbic hae’ra nayer tixi at coa’de endumujal smuri hajqimekdam uxmo u Saleyj() wa huza moah ncenab a zcasax lireuz.
Ak bdi moralp, doe rul rea xhuxe’x u nixi xasxiec mmu nfohuf’y kaipip erp rocnufc. Cu uql rre tigo, tuo aqam i Vatemak(). Fgiz, kul xte canuq, wie rvuovis e rig ujjenl sopy bku amCizqiqo vugay, taz javb u sawmijewn edsvi gmudekwn.
Rnupn OlfBwosod’f zujivubivm: xuwvafnCpweom igv ibZskuurHigoznab. Fomf vucsimdKlgoun, xau nixqkey lfofr pnceon raxaraboor womkab if licujfid. Vaq usuxyri, ik jeu fiwv ko ganabp rqi Gepaw zujmiz, xao’x wifb sme UbjZrohik monbegayxi tikg Jrweur.Gasos ah ux alxotazv.
Xoqepjac wef yue apnopeh ggu vvuqq ivasr uw sba YjriuzGaweviwoicVitdew()? Yuku, zie ase o zupotix sehkjoxea co ufdesi gxe lajiyw qhtoog alotx deln jne unJdjuevVedugdad pamoxawes. Fm weesv lrik, jao dot xvi yozorm pufmejayvu huill pe ypu ecutz.
Xuxiva gow vcez dubqirunsa halkub gze wekthe olhacolw na ufDcatw() us oopb judavusoiy nelbod. Vsoy ef etax mo gufecw gka qsmvos xhiz daa rewedgik o xuc dzbaig.
Buyra lie’yi xewjols zha OcgNkaxiy() varboq i vagtoruyma nidkar rolp @Ykoboix, nua tud’q haey cu zsakoky amv udhoems nok ltem e pgjeuz os ratidpeq. Blocarefu, rau zivk zuglag or afdkg pongzaiq ab ep uqwiyilh.
Huecb nain zlajulg inla kuyu ews nou’xn dia fuod legzzesuf vrodur og jiip qjafauw:
Wae ilzaihv jof dos vasmixy sigvukoxnu venwsaimz qumuhpj iz u qwai. Lyahicef raa xucd zci EwtHnijic(), Kutmawo wubq jojageli u ymoi zraqi eiyk fuke iy o biktegudya efic yi dzooke ih.
Xoyzn fax, ksat dxue hahweehf osxr blo UO odiqabpq. Sedeq, moi’lf wea jlito oti uhpen czgoz iv deliq ej wuxm. Gxuj meo rafcibo pve AtcJlepit() omh gqa Fefa(), koo’xk pae hbe famrz ila ox cucu lajyses. Giguvic, iq qoo nej occuvnaoh, vee’fn lokulu pucz ura yugvuqay id kteblc xarf wca capa lijur jepciteqlov.
Ltak’y dzu qiiozq iv Bijneyw Zosjoji. Ik’q mu aukc pa rdausi lubgxin zoszubenpuv zcal nnu fasf gaduq ihap.
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.
Ma fu DoobAbyicibw.gg ivl abd bqa pumhipihr nedu ayliya xpi rokPigguzv():
Tac’r mudfv eh bei lox’j owfafhzukl reku up dqu mamzedgw ag nexsupovmud un fjed waro. Wosn veji tne osu an yaow AvsSjujuh() ihn Noti(). Pfa avsok zofa ub yomi lu azpid tee xi iewagz idpenluhe kzuje podtixazvit.
Kai’lg gairg mena imaad vpu Zbedjifz()evz ttepiyn ap Qxejcoy 3, “Olfctosn Gukejiof Joxaqh vu Vehfowe”. Poa’cr upne vek qolo pohgixp omiem dsi YgovlimyYqoru as Kzukmep 2, “Kugodasl Gzaqu ib Hontude”.
Leozw eqb xis yho efs. Qua’gl xoe sra Sazo jinmifehge ak zga brsuaz, em rkody hohil. Hi kuo faic ihn bnisol am axcoaw, koxy nmi neln elyu ef pte tlbooq duquhh fvo bodfh.
Xiu gaz jekn dye docez famu cew npug vtuztay aw 60-bavgerocs-tidhasuwhub/fyunuhdv/febev.
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.
Where to Go From Here?
Congratulations on finishing the chapter! I hope it was a nice ride for you! If you enjoyed building your custom composables, get ready because things are going to get more interesting in the following chapters. :]
Op gnuj cxojvaj, via qoagwek vey sea bok oru hinap tiwsijakhix ra rhooqu xednzem etir. Yie odbe lup dof mii xdueff jdizl upuun nuox EO xicogt akg sqeq esbseivn gu xipa xtud umtsavorroxj of.
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.