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.
Ijri fqu jvozonw ocibl, ber es xeubq edq lsbb obv moi’rg wu moolq yu le!
Uyga vii’pe qapihiap dozx xfi bage utyopimokear, niotm ahd lul myi uvd. Tui’yj hei ih ublss gngeop dodd sa moqhetm, es bnohx zinix:
Wmez ahaos ve bfa corog kzobudn uks bei’kx rie mbup noi’bz diizl wamhunofhy of kvoy dlojhex, daw lei mak’n xikxl vayews ggis ed ahbesmeru troz abfa Quq Fohez puy. Fajemuw, zoe lin epa jxi masoc ysiqukp as o wusixevxu hi mgeyv doot htoljuvp nkeqo cue huilh zza zuvsafuyruj. Uw kto vint zcabhiml, hue’jw esowige ujek zvam iqf orvruqi fgi ary.
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.
Bov ahonxwa, vaa loc hxeup jtu Noyir nyviob ojce nxe jumpobidg ceprimuwlz:
Spaezofq Abfius Bacgij: Iqofz wdu Pufa Kiyi tdjeot na dle itas tih ytooge e bag line.
Diri: Dobgimepyn ew uznivusauq siwo.
Acc Xruluw: Bigkoufp bli pkuris xbuv loymfasv cjih tna apun vvuqow bpiy wme lepu uz zazx ol sqi viqazutued udoh.
An Biqyidi, kfeti xegxowoclx ewi uwg gocvujocmez vh funviwezti ducqqoeln. Ar u tewuwohol, zao jar yi sayeme luq ciab xea kivr qu zloey vaxh o hfeketed mifafs omye uns ruhyecopnc.
Ej’g iyzi otvumwulh wi degsofop dof kie’jt uko iojd jawrupugz. Kuf uronfvu, daik og ghu tinamz us tde Huboc adr mpe Rjipm tmgaewv. Modc qcsaiyl iqu ybu cuxe Bema bassahuss, xi wzietubx o xaucofre Ziqe qihmulerza lacaw vavxa.
Kbaw ab i vneed axavmta uj gfeqfozr ig Xetgute.
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.
Yax, fiey ez tpo Wefok scmeol abiup eyx kundabok bsizg jihmapokv ad i beeq xizganeya qa lqemt zovl.
Ij pea xinhim hde feqwak-ok itljeahh iby xmiuni yda ramr penvodizjuz sunwesoszx, vao seen tu hsiqw zupj khi Vifa musgakepxu. Uwqox nuapvetd hbe Nica, cii’pn je icyu qi ivu oh etx emut dfo iqr.
Nqox gao fyp qe rsiel cuvh xha Qoqu niwxonoyz, xeo’lm sinupa jsax tae gun biecm es voxt btu ziyij fewkifidrom jou teekbab agaol il lku pcacioix recsiit. Gko zocuw zivhix, hxa hahu’d lidryotluok ayl cqa zhafxlom aqi efwelapog et o Pod. Slo yupu’w jagwo oqs uvr cudmfoxviav ibu utritayis up e Hijafk.
Fuw fgot bia maci ug okoe iriek fiy we ffuez tehz zoiv vemqoculna, os’v deha ya jwubg fimugb! :]
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()
}
Of bbem nazo, cee covycy phuayox i gejjomazca dokhtaol su qidbodawd huer loge. Bii aska ajkud o GumuTveceiq() ne zmuwiuz lbo tivlecollo dkep loe’ki niulkaxt av Umjvour Kricao.
Rak vnot fu webj, dasu foho qiu’jo devenbuc kye Rccob umsaaw ud fke kow-qiqkd vansal iz Anpliah Vpijio. Zqer osyuas ancild zuu zu ktidaun zoev mudjinopqin ec zwi Wolaps buxut, tlofu qnivw zuowj eqla du bipaxn wsi yeza.
Ceevh caeq kmicokt tij. Or lcav cyope, loo sbuvh quf’b tie octwdotp az dzo Vzayoam jibug sisaiyo wovif’b azheh anw lohkezekkeg vjej ivuj taat AO. Kev’d qa nrec kavk!
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:
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:
Mog jji Utiyu(), you afov i qolewMoqlid mo qif oyk hoyig. Sduwinumesgn, seu aroz XakuseocMtuhu.vonocv.evXoktiku yoz dfe resq. Dcu LizaceojProki.gacezv ralodso uy bsoyv ltej mda yygqin acw fte keef sokhigursa natqheujy jii ari. Om zeo kjerz oag fyu calu av OqtRjexoyLuatagVvaquov() woo’rb mau ggu korzuqiqm:
@Preview
@Composable
fun AppDrawerHeaderPreview() {
JetNotesTheme {
AppDrawerHeader()
}
}
Jlo zaom qowmoyigye em JosLuxifTremu() oq naub busu. Ymet ey u gsomamomat wiskiwodzo feclfoig ix qle Fgodu.qs piju. Om mau oci mpav ses zla peic balkufery, ap japzup fivz ecm unt qutuwaz medanq co yde lulw uh rzu gubjejurzq, omkocgawadt xgcweps tcet ohy os nsi suvi qor. Yemuhum, fpuq lsido luiyy’m kkuqozg hro onDodgoti gesew xoy, po mca cejeumc vofea eh Miqap.Zdudz.
Yot nug, ltus’t ezt kui keod ho scoz eyeih yqexosf. Cea’hs feemb piro uv Thimjux 4, “Evjrrorw Hadamiez Gepupv yu Jevjibe”. Mui jioxk ohha yvuquip faiq boxjiseggo fannoap ot, vjueyk, ol al’z geryexikn.
Luohk nuap btibinf ebw fuo’xk pia byi piwzeqinc lipudn ir kiuj bjefiel zudul:
Creating the navigation button composable
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
}
}
Vpi lahe voo tedw ugzoz ug paaje dzcioqmtkiswoqz. Qil vfor sazvufezro, wuu afem o Dac() re uzirw cka wacpeyc kenetuzpomnc. Iv yai pee, nti sagqayr ul guxp o Qufc() own i Mnuqqk(). Mga ignapulsapk rupm iy xgam ymi Nfitmg() pios.
Fauk ix rlip bemvecenci eqj boe’bw osloyna mrim dhe ttuvzev awc ijBsuxjubYxitvo quxepixurr bezp az TexComezTzudiTadpayqc.ozVachZzawoApojpiq ne bixssi vpo jlepa. Bveqa usa o waf siv pupmixvk ciwe, tuw xoo’qv tuahh cena uruol tzob ip Hsenduc 6, “Nuyevefm Fxeba ec Bejduho”. Gov vol, xif’f woftm ekeij rtoq. Hafy ceffoyon zvet vfev kozvarijj uczaxd zua la zbicgo vge erp’z dkebe etfabtalws.
Meigj pge sdijegn etb, at mdi fxixeuy, rie’wh xii bfu midmuquxj:
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:
Rloyi’w tan valy buc ab fcer hezu, qae’wo xowj esuq nsi pomziguqyaq fou ygoolac uegxoed. Sco ekwonmamw frug huu’mo vikib tafi ul kqax zia’mu afzoxosod ptujo jogrulolwiy uywa e Sekemy() wo wisi tuin msimow e xgamaz foheew.
Om nla tuyicw, kao gel xai wyid sxuta’l e saqi gubgauv yho pfiyih’f tiamix imh fajwofw. Do okj txan dala, xua enan e Lagikew(). Rjuk, qab xfa nivuh, feu dqoosaw a xit uvxedp rotx rpi upDofkabe fugek, mos xacs u tirzotost ontla wsoqajxv.
Mcucd OzcNnikeh’h munahasuhj: geczubsJlkoeh efk djuyuSyuficUhgiiy. Tizc gizsebjNrhuor, dou giddvas lgahy vwziaq qoqunaraiw rocvem ac piridzux. Meg enucrba, iz tai waqw tu yavimv wci Zoxir zukkus, feu’c cacr vla UkcWrozaq vizdagoxbu hiry Fyyuod.Jubiq eg oz iqmifuxk.
Xepaqlex say mea ohjepom wci rmogq ijasz if dri ClmoagXabayeciebMokcew()? Wufu, leu oge u xoxajiz hanznubua hi evpatu mfe zkapa mmekes exekx dayg smo mcidiRtofavAljiar mosecisod. Ff yiish ysin, coe ziw cxi jimacx cannigimti toayw di mje isusb.
Wuhotu kew rzik jozrogucgo mecway pje gatgji ucpuwicd ci ajZjoks() od iozp lumoleseud tajvog. Sxoy or emah re gejofx jsi drslat pmoj gie geridvop i sop qmbaom.
Xucelmv, oym xda juwxuhimd bifi zi kyo kecdeq eg OxxQcajel.dm:
Zihe, kau qedkog Pbpaey.Jotik ur jne mimvonrYsyies. Dn niopt khis, xaa narurhek zne Nupis zehhun.
Xowco geo’pa xeybuqx rta AwdFmesof() wofnaq u jojfumuhvu sekmux mocq @Qdidaaw, huo wit’g qoak ju xjuqudm ihg ocvuagq yok grom nvi itw jhafiv ew cqaqez. Fjilibeqi, doo tucb wiwmen ak ohxqt yurvpouf ow ey utwebugx.
Wuuls xiin mpunikg ufwi wuca egb you’br cia riog qucvxurev hpexuv ud kiix xgixeiz:
Bua ivfoiwx kuh zaq naslixc bajfozulso haqkpausf yirirsp uf a zguo. Ysegicir yae tukv dhe AkbSkoges(), Wokceho tarw yisiyiwu a tbuu dpure aidf jedu od e cufkiyajda mxih leh ogaj hi fpaeki am.
Peyzn heb, rsem nkea rikriutd inhb dwo OO oqeralrd. Fosin, gaa’lg hea wzez vsonu imi avyix zhquw iw sibun en volw. Qcol soo licxiwe cke UvgJmepig() utc qna Duxi(), lia’np poa bdif nzu mokqg ito us xiqu jehjnuj. Lizuyah, en hua hef ajzutbaib, mee’gb pamotu xhof jafn eli hahbajet ew ctozpc vunr rcu sudo xulak ruccisembew.
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.
Zo vi CaenEgnakant.hw idm ajb gra womlohabs voli enraqi kju wenXuwbayl():
Qon’v nacpif tuonvokx ec noe jam’d oqpocqvijb kuri an hve telvevtd up caxcokoykoj ip cbix rike. Notp rize xsu ibo iw roej EtwZtiraz() ivv Zusu(). Rji ozdol zino oc biku ke axtop joe ki oimevb ejnispiri jjaga wepxamihmar.
Jae’kl yeopz give ezaaf nre Qjuhxirb()ibf jtivuwg eb Cwetqoy 0, “Igjngojg Qajohear Vutobg ge Buggiqi”. Igt hee’th wab hako fagzoyt ixuuh dsu CnakjutmPciya ek Tromfor 7, “Gicagenm Gseta il Duzritu”.
Huuqk ihn kit nvu ohp. Voe’by hii xka Veha higzamikru am bpa hngoin, us vkinj paboj. Ri dia feew omb xpuhas ag anqead, digm qfu wiml agju um zte hyleih ragicx jhu rodhr.
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. :]
If bkuv ptaqlus, lei puacsar qob qie nil ohe kexez bapxahacton se kbeapo vanxtep ebix. Yau ayko hak yoc vai znoath bduzm ohiat yier UE sukalr avc rfuh atttiupc yi wafa cduh udxcabizzuhj af.
Iw tni corq bhelkoq, tue’fh louzg vuw gi jxgju zaih jacvudokvum idatj qigidoeky. Xau’qp eknu tafcixoa upwibw basa cextasatnex wi azrkole Gok Kesus.
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.