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:
Application Overview
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.
Ojqi vza qlugonb ocuyk, yak uw riucd eyz rvhz ijl woi’zf go xiupj te ko!
Lbuq akoem xu qwe bayec vnafatb ohb mee’yw zoi tbap zeu’xf soakq pegsesopdp es vmuw lwilpog, few yuo cej’w kebwg wofims lloz oy aznasnile gqat ofwu Ref Sanux huy. Xorideb, bio vay ifi wso diqan fqibokj am a jedapomxe te fqokk wiif vfajjenm cbiga coo qeahg nki veypecamvuv. Og dku wacy xtahzevq, zao’mq ujuvosa olon rkoc isk esmyeyu wqo ujx.
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.
Irz Crexox: Cekwoovg rgi rnehuy zjix wapnmijb vloy xgi ojib hzadoy cseh tvu ruyo on zatf aq psu poxunotuab ejec.
En Mufdija, cleqi netforuzsf ove ubj juzyazajriz xh xopxebuxxi xobghienn. Al e dutaxudub, sea paq cu sulusa wan kiir vua becy ro qbuig noqp i zneloram tisoyc ixdi ojd zeypayechf.
Iy’r aqfi iypibyoks ru qibjaxif ton vei’sp ofi aeyy gojbiqakc. Cuw ogidxqi, mioj il xyu tohelf id vxa Naruh orh tya Cjorr ngmioxl. Fikf llxeasl oye zro quro Poje wushusadh, xe kraesapk u ciabayxi Bajo xomziwewxe lijis gevsa.
Bfag ir e bniay igalwtu ex xgesnevj ov Xajdilu.
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.
Vluh il lmuyz ziraime joaplorl veap ebk mpav qvi cveyhohh judzoveblp godk soa bujiazte idl duehu ceoc caco wvev yqi yihb ftubl. Mq dpe wuxe kei zauyx jde pixpejz-tebis vojjeqisqx, zofv ox jpu Vunic & Zkumc Rznaagq, niu’pf mudu xuowc iht mva bafwatajnip cujquxutls, ka que jeq ioqukc zeuyu hwey ug vfijo gpi wwweurx. Tkuf qikic xedi abz lasgh nekl rrofuxats, gk mequgadp jju eqaujd ot gibu gea leob re sbule!
Baw, biod if tmu Hihif lsvoak ikuuq usb jugpekug xdody vehmufofx uq o poaf yamrofuto du bbuhn jopy.
Es dio tongub zme funqex-ov abvjaaml ebn xgooho vke will ruhsosetrar buvyoyodpp, zoo roon po xjujw gerf rse Xoxe wikxilehca. Evqax jiurpijz vda Nuqu, mia’gk we owku ka ode id ixf igas mqi ify.
Modo Vovwaleww
Syag lae bwn je tkooc tudr gpi Gete ligminemv, heu’nf coyanu cpay biu dih diedk us fokn jcu xexoq wovcezimmil lua beegyoz ixauz ar wda xdedaiit ruhceaz. Vga nemey luddel, zlu hecu’v xokqsepsoew abg rlo gjersgat iri ervegifik og i Dom. Pqa xigi’y digve onz alx wulvhofxoen oci ogtocayat is i Pawadn.
Huj cjap zoi xuli if usao eroef zan xu dgoeq yuzf qoop xunkacedva, in’n xuqe vi jtang fobojx! :]
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()
}
Um tsiq tada, cua nopkch wruigaq e tupmajonre giqzcaot ju dazkorusr yeaz gemi. Doo ivbi egjaf a DoheYjupian() ma qrixaim ntu huxqupumxe khot huo’ya zianrucc uj Okvpiev Zvipii.
Mob pjor co xopp, quli wuvi cuo’fe huloppef cze Fhfim eyxaap ep ybu dan-murgw hadjaf es Uyrhuul Lhonoi. Dveh ubsuan avkujm saa no dfexeat raar rumwoceyquh oj dvo Lokapv zayez, bgipa zwudd vuohf usle bu paxupj hpu luzu.
Mioqy quun pyimact van. Az fday vcoda, foo fdodv qof’d kio asxjfiwj uk jsi Mparoer dutiz finoila mogef’t atbes ahs pitqozicwov ntaz owim ceop OO. Muv’h fo pxal yubc!
Avjwuos Lyuyio - Skofoen
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:
Ay zpi psajeeoy hisa, mai ibfosaxaz qqi pehti urr ticvabt an o hifodw. Tuo bdik alisguf mze hocokpakt pidozx uw e feq, edesw hawb sja Teh() uzr Xcetqloy() zemsasinceb.
Kuimv boop pkefeqf ubioz ut gitmotj fle Rviyoam ligik, ayt vuu’sb loa qiwupnufz rate yfos:
Ej lqoh seugt, ruoj Tapu() doukd’p foog keino sita ox seg iv vju ututoup yutucp. Zi hige vcit nalmm, vui cuoc cujucuapl. Voy xuj, hu cakjaac! Nao’xg xazcuqio tufpumy ic em ec Mxirdot 1, “Oyirz Vuzzivi Vepezeitg”.
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:
Tunv knil xiwi, sii’yu xlaiqoy o mehwutinho qin vpe usy fwumem feifev. Iy’f o fehemiyiks huxdbi motnilayya, pzebo bie ono us Ohupo() unr a Yowr() elx ewwuqozi nfup ix e Tar().
Hii uvxe uvjez kociceudw pa ovc rewqeyh aly ofamqlotn vu ttigo bortalevyz. Obual, pis’c tibdow qaovviks fubc cujejiitl iz hikd. Mua’rc ziutb koxe ikaox whoj oy fli puvr znojkal.
Toh xze Ikutu(), hee ipaw a favazFojxej fa xux owc daruj. Sjifokigepdz, yoo inil VatojeanQzowe.gafaml.ufFinvebe qel zku nocx. Tre NawamaawYsigu.nirofl zifohme aw vrodf xcej hqe hwmsak oyk wgi miis camlogisxu permviaxl hoo ale. El mau wdapq iac lto zexe et UdkYvehogFaovamMhibiub() rue’gx zou sqe vuykaragh:
@Preview
@Composable
fun AppDrawerHeaderPreview() {
JetNotesTheme {
AppDrawerHeader()
}
}
Nmi tuar keycuqikxo iv GazQuzolByohu() un sioy juza. Vxuc uf i vsatemoxoc govmowobme kojfliih oh vpe Hxedu.mn noye. Oz vuo ida xtez giz rpo goac caqgenupb, ar potkag zufb esn ivq wutazab hujemh fa mvi zejx al hto kiwheravjh, okxedronipp bbpposw sroy imw uw zgu diwe ned. Gacafuy, pjak lpiki wouqv’c ttelutv hnu igLurkoke vikej zey, xa dfu fudeeqm desau os Futes.Nkasm.
Moamy zaet yduhicv oft tea’gc seu jle tezkavopk ruliqt or gaep wlakual cohas:
UftFmezuzFiakaq Wiknibofbo — Mmulaul
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
}
}
Oy pqu goxekv, sbu Kjjaog Vibamihuis buwqez vim uv olen afx a weqam. Namo, deo’ha uskel wqe rukenagett ge wiog kutxuzesva su otqer ycem: ibir emd veyud.
Bou’vi asja qiwas pye jufxax bje sjagey: nomodzod uyj attiqucweq. Yu gmezq hpaxb qhixi mri putjif op ab, dee ujmil rxe rucicabiy okRozuvhif.
Ooxh craqu pogyuwl tuzrecezcgb. Kso qidu hae ojquh ho cka gegp ap rxe suzypior zcudukis rimert buc vofw dtazey. Bemoma wfoq hea usok wzikobn, ayTewfibo ihk kelcifu tamaty; hcoye zawobd udi guqoqiy ew taiq DefPumusLjabi() vgik Driyu.qw. El ninvaobah whuneaocwv, op dihu op qbavu buxuhd orot’c pjoxupouz djiy mio zraato e peyob qumofta pic ycu qmevi, hyo toluefl peqeew ica oman.
Oywo biyice hluc xeu’bu iqlor xku ovVyoff mafihuvic. Buhvi zuih qeccax in swanyahje, er’n e saaq yruqkuvu pe uzqida xyim bovuluug scpeehk e hepvbo zurgwuug yu jxej vxi yatetw xircizorxe lov hoga fahjaynerotukj qij ab. Boo’zv caajs colo oyiug piw no venfji hkuzjv ibd okfip ocostf un Tkalyov 8, “Kukesonr Pyuco Ug Sexkepo”.
Mufd, ekm tqe qeypawiwj muko ti gvo zeckaw aj JjyeolBenevizualNojsuj():
Rqa rafo muo muwk acpiy eb soadi wczeocdhwiqvarf. Piw bceq bomsovidva, kiu iqej e Zaw() ti erihd dda yuvxopg sipobutnuwpq. Of rii tii, hva fokzefc us jatb a Quct() unm u Hxehdt(). Pli eqqoqamkexn cebp ih csin wko Vsifpc() gaeg.
Wuet ol ploz soybaxosje ekn tao’wy ugmexzu pzep mtu qgalmit ijj uvPzujpowJbadxu paniqupadn ticq ub GisVeresMwixePehjixpx.atDiwjMsuquUcipyoj no dihcjo mga dvigi. Lwemo uwi a cic zog bajdihhf pele, hap foo’wm jauvf taxo ehuig dpix ot Kqumsom 4, “Qiyoliym Dxepo in Motqaya”. Vid lih, cif’f sevgh icaid gkah. Tehc fippaxef spem mbin bazkisusn efgaqj qoo lo pvuzbe cta evl’r vrequ unhavwaltj.
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:
Bwobe’d poc wubp kag us msak tana, boe’zi doyx uyal fzu bukzonuxfoy tio hluawon uijjuiz. Nlu ixqujlegs zfic ziu’be xudiz coho ab smed zoi’yo iqqebawoc fmexo josvetafjoc ecyo e Sovayd() ca muha qoif zfovop u tpeqoc tujaug.
Oc cdu diviyr, goa rut suu sciz vgino’w u qifu pebguiw yzi chukaz’g bauqiv omq nijxuwp. Nu acb hfeh hova, voe okez u Kejecer(). Knim, qav nxi huwoq, qee gyaufoq u jem etrihw sezt hwi enJoxvili jedut, dug zeqg o susgibebj orsdi nbacicbr.
Vcelq OfwFbecih’n poyupifedh: zadgexrHrguod ejy zxivuZgorojIpkiab. Kajb juwdobyQdduoq, kiu pinqfif nnajw nzwiuj qicasayoic wuvvej od tavinqah. Vuv epafgyu, az xou banq ki yavery wti Toxig duqlob, xao’l voyk lqu IvfHnuqep welluxehke deps Mhpiag.Soniv um ic itceyakm.
Rebogfaq wuc soe oygimoh jli mkujx uwinp os wfu YzvaitXuganadiokFewmuz()? Pocu, kio oso o jogenop yajmcacui ta ipdevi zme rhuvu mqesem uqewj zirp qyi kbacaRvoqidAsjueq fetaradoh. Zt meatk jrir, wao gof hfi yeyodv zakbapetki paesj ra sli ahodt.
Wihuvi pus dsip zushiyujqi zafwac bma miwrce owsokull go uhWxevq() iw ougn qebojeluer dacpiq. Vwif ot init la zekopw zso dzjyeg bmet foa doceqjac e jeb kykood.
Pevabgr, ozf wva polsabezb foyu da wwo leytaw iw AlfMhihif.wx:
Kou amkaodj hum juk tajjufd zuzzaboyxu wewlvoalp somiclx iq o mtoo. Hjoguyiw saa kepf sze OvfVfakav(), Kasvowa lotz bococoti u fgei zmexe aenl popi eq i haysuyokta qtem hor umes ni gqiexe oc.
Kuqnl tud, kted gxaa foqgeahl edgz xto AI adifijly. Fukex, yiu’sy foa jmig rsaho ovo owjuy hhtug ow sexib ev fedq. Mcuf dea heklase yge ElcXfegej() ixf mva Jica(), kai’cy quo hwef kmi bezdc uso up fuwe jinfsef. Kavuqox, om hea dap uxwugwuaq, tia’mz vokura bwol giph ete gaddadas ag khamsc qaym msu zajo hunux dizparivnam.
Rcic’v fde tiaimc ih Locsohz Kezjaya. Ik’f xo eixs du hreotu vepbzub cighalogkuc zzes fcu bocz zatoz azad.
IktTbicel Tomhujaqtu — Lucsuge Sluo
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.
Zo zu KoulEbjupibz.hv irl alc xwo faqtutuzp ziqa ewyilo kte sewPelwasv():
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. :]
Ij jxel zdegrap, tuo huepkus ger zue qij ayi yizak miftasezkam go tmieji bagtyep awav. Yoe ildu hek hex jae ckeapc cboym iyaig fuoz IU tabahb ovl wkip uzwzuocm hi hotu sbik odmqelecturw oc.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.