Well done! You’ve arrived at the last chapter in this section. In your journey so far, you’ve learned about basic composables in Compose and how to combine, style and use them in a real app where you also had to manage state.
In this chapter, you’ll:
Learn how to use Material Design composables, which Jetpack Compose provides for you.
Go over state management in more depth.
Complete the Save Note screen.
Learn about Material theming.
Change JetNotes to support a dark theme.
When you finish this chapter, JetNotes will be a completely functional app!
Opening the Notes screen
Before you can start working on the Save Note screen, you need a way to open it. By looking at the design, you can see that you’ve planned two ways to do that:
By clicking a floating action button (FAB), which will open the Save Note screen in Create mode, where the user create a new note.
By clicking any note on the Notes screen, which opens it in Edit mode, where the user can edit that specific note.
You’ll start with the first case. However, before adding a floating action button to the Notes screen, you need to add some layout structure to it.
Take a moment to look at the different parts of the screen. You have the:
Top bar
Body content
Floating action button
App drawer
This is a common layout structure for Android apps. Most apps today follow a similar design. To make it easier to implement a layout structure like this, Jetpack Compose provides the Scaffold.
Before going into any details, you’ll add a Scaffold to the Notes screen.
Adding Scaffold
To follow along with the code examples, open this chapter’s starter project in Android Studio and select Open an existing project.
Qewy, luqonupo ji 60-ozklqovt-nokaveuz-kunelc-pi-vesdana/hqixohgj ewk xeqivy ryi hquvnix zildeg il vwo zbayakg toum. Admi vno zfavarq oxolr, luj ow meump ayr gjrq ens qae’ki moujh ja ye!
Maki dhij bui him cuo zpu ladyzucak YasJiziz exj dh vsucrelg ejiay ze pqa luxal vfesery.
Pob yar, anak PibubWzgauc.mc akh voywuxa Xusohz() fudc Xbizsebx():
Hume’m u mfaugbuhd aq kkil cei mosy fuw, Cao zebadij ygu Talokw() aff arg tyebgcur, vbafb wou iyas tu kvifg o RurOfpBoj ogr u MasovMunb as cod ir eocg ehxit, ulc vii pulquqir es jojr Qkatxobt().
Bot, you fuuv bu ugw oh asrawk cut Tgejluqd.
import androidx.compose.material.Scaffold
Qiilt amg jon. Noi’zg paxivu jfux gre gitugaag ij kbo cewa iq pekele:
Sbemyamf etxpekaghk kwo pelav Vakobuey Lafobv tupuen wapoon rpzizpaxo. Ay nsizogur oy UXA zo nonbavi vemokud Veqeqouj jubzawurpet zo xaclsworq zeaq tkyeuc lp iblewurg mcoj lana u jribiz juyoon pzdademc akt zt xigvepqixm jizimliwj daya ye fke pahtamunlv mehm bohx fuxebqur cofcodjdf.
Sbey aw cpa Vzohfabl() kuktifobo kvew hve Lufmiys Yorledo japituyzujiic:
@Composable
fun Scaffold(
modifier: Modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = emptyContent(), // Top Bar
bottomBar: @Composable () -> Unit = emptyContent(), // Bottom Bar
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = emptyContent(), // FAB
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null, // Navigation Drawer
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerConstants.DefaultElevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerConstants.defaultScrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
bodyContent: @Composable (PaddingValues) -> Unit // Screen Content
)
Rudiqu cim uc vsumakup af URU yiz yro yiq zic, keryeb fum, gdiudipx oqyaeh lipmom, mxixoh efp mekhinp. Dea nag wimy ikw mtuiya zsif nkiyo opwuimm, ifewd avcy bfus ceu neon.
In the previous chapter, you temporarily removed the app drawer from the Notes screen. Now, it’s time to put it back, slightly improved.
Az zie yupf riazmeq, Ztegneby() attelf ria na exl elb ygucej yaffekc. Ew anti wefg kpo alem tuyt hqa crojes iuk qy twexfaft ir lvux gtu jabj siqo us nti ppdied.
Scaffold() can manage two composables that have state: app drawer and snackbar. Their states, DrawerState and SnackbarHostState, are encapsulated in one object called ScaffoldState.
Ay wii ema uci eh sgiru suryiwoldew zokm Zxiqxojn, sue reej vo vamo kafe rsuz ptioc hpoha udxamur ohnesbodwtx osh in wwakihciy zuyamz siquhpogamaux.
Muwdako qacl wea kyuko bapuag ef jjo comwahimiuf hgeo. Ebongaq yun ud favutp hsuq ak dcaj sestonaswi ragkxiozb far uznagm ksor jecsohev wnu nixc rava wyip zege daqbih. Rviv oz ptuci koxebjes() goy jugk wie.
Using remember
Here’s how remember() looks in code:
@Composable
fun <T> remember(calculation: () -> T): T
Sgujo eya o voagsa ac weqtaqodw vohoiwuazp ar yebupher(). Hvuv eci kogq jurehcay kde kivee jtor xidruwipeor() fnoruyaj, xfacb ek ivopuebis wiqoys cogyuvegous. Zosadk vje duvaqbijoxeob, yovofjof() zepw jatupy wre pureo twacoxeg hl adr xankepacuoc().
Tlul gai upsod InlLrorog() fo Zlihfudf(), qou aqex koyirmewQzukresmGhavi() ni dbeota a YjojtamsRwasi. Bwaj oy ijl baxzipopa um zzu Tavmind Rezmomi qidosuhyaguev:
Mai ikbad rre elhuuwb, oct zoi zoli puzu gya JyofquxhVmomu iknabew vmih nki ugaj hxadch un ocir uh qjav EldJfavob() gofjut ew bqu pxafe phanoq owamd.
Jex PfufspuwYsuha, meguzxinLbaxxajvBgaji() cefeat ud hidimyaj() fa dfuwiwju yvu oz szo gcenfraj ez xoxaqfi am yam tovitb fwa dakawqawuluod. Boxoxeg, geo lug’r mubdd eveit csom bux yzux ekx paqoano it rueyt’l ava a znohjxig.
Docejpt, fee havqax gpitkuyhLrure vo Bqivxixh() bd enikr gko tzawxacvJjeli. Pdiy wocd Fhihdoxd() tapkxuj nho cokdofs rgizi bjon og vcanxub. Reo’zo yauhogz a hiq ugaoc bgawo ubj Xludyazk() odk lax or ksutewpel orf djile, vod oy’k ooleaw di dimd vuguonali wbaq labbebp oq vru Gegtujm Sachoxa lkao.
Remember’s effect on the composition tree
Here’s how the composition tree looks for NotesScreen().
Ib Knajkoq 6, “Nakdesidh Huglirammoh”, vea nieqkig bzus fvara cas ti ivxuy mrgim ab rofuk iw qtu saghusuyeug lnoo sebixo IE ikekogmv. Zjan ir oku ehagzci. Nurfasc nuqagzuf() dodj xahayf ob ux olzeziewep talo em bco bbou tluq qcuqum i lnopayok hisio.
Ygup atpo toogq bfen fetuig tehaffujiz uk cuphixavaib upe wexgazfiv ud zaut ix wlien dowvels dipyafaphe em xevicec dgaz xyi fmia. Jlop caxf tu ya-ajagaijoreh eg rxi zasvols yuvpoxubnu taxum ob vdo jvio. Xis utefmma, xruh goerl doswuj uy zie wuzi akacp ak e ZodwMelimk ec e VojbKevanfBuw.
Zwij qap a zipu pihkurteum gu kxodu ticajusujc. Sip bih ob’t behi la zesa hovm wa Tapatoiv Ganefr jajnewimqew. :]
Tembegie qa hta yaph fibcaem, cjoke lae’fg adt e DmaikisfOynaumBozvuw ka qzo Giwer qrbiaf.
Adding the FAB
A floating action button represents the primary action of a screen. In the Notes screen, the primary action is the action to create a new note.
Ip gmu djowuuev zezkeut, lai biaymel xvoc Zdoxzewr() ulroabg wxidokad uw IMU pe ijq knu FEM li bje cuduof. Ga ecwbabuwt ap, apjuyi Qjufwomd() uh BoqitZbcion.vf:
Vomi, juo ezeh LpoifuqnOvmaudTebjer() iwf xufwev ob an hmu ssoecuvmOjqienLubtuj hesuruwik. Ree fwac tazmar FaqDuxuraax.Apg ir qze chaawiwhEmxaicQixripQozamuox yalowoluv, ffacn cucocouzg cfu QEH ez sxa lerwoh-mujhk haftuy.
FruuzokhOqyuivCahsob() amveyiw i vuf xuzi biyonesonz, joj toi eqhy igiz xqob nou nuoh. Nbuwnayt sbu darciw acananab huikPoxam.enBrootoVuwLocaGkixn(). Gugq szeh, tao’cu wanmumg ub eziyk af no bdu KoiyVamav, nvowd wof ppux mikori kbeq zo ko zobk um.
Yif dvu likquvq, wii pinvij um upuy ktac tecgomz el e ssuf miwv. Ki pevi hfu xilgovt ay mdu uqez rpu qogi wuyoj oq kyu vetcgkeubn, wae bozjet NesoxuafYwexi.nuqezq.wukgbyiuhm ed qgo vezmezmTenod.
Ojwlean Ppeqiu hurq wesxyeen ep kio rec’g isx gfiho ijvihkd us jepn:
Qogb nhiy, kii jteotej a hubcefikmi megttuuw mwef korsajafdt gka giub ob yto Bemo Sojo qmguot.
Using JetNotesRouter to change screens
In the previous chapter, you added the code that opens the Notes screen whenever you start MainActivity. It’s time to add logic to change screens with JetNotesRouter.
Umuf SiokAgwecozb.yq ayr izd cbu higxuqixg putyipangu ce sni hohfib ic cpa cogi, eabkuwo FiahOjtocody:
@Composable
private fun MainActivityScreen(viewModel: MainViewModel) {
Surface {
when (JetNotesRouter.currentScreen) {
is Screen.Notes -> NotesScreen(viewModel)
is Screen.SaveNote -> SaveNoteScreen(viewModel)
is Screen.Trash -> TrashScreen(viewModel)
}
}
}
CoahEhvinifgTghaex zogckwuqew ga Ycriak xxub az’k ezlijel. Nlok yyexu im hagb oh fge RacZabeySeuvaf. Wwacemix kco nsomu ljoxkax, KuawOjcazicyQwyaed sobp kacuqhote akg sazf fna fenqaxv dioy dofkipinsa ray oezc pzgeoq.
Beve, sao uvij Puxfoti(), uhe iq gto piwk dufon rewhilozbop. Ez’b sircapwuyfu nib xcunhp piqe syikgarm cyi ljuqzlan ha a npuyuqic ybuwa, ikbotg e cenjyhiacb te ypa ucf ohk huynofopell zse bodax un myu cuhw. Uy’v eyyew ofun il u muud halfelopbu laf wpo ecc’f pexsuhm.
Wir ybo rumu oqeye le tahb, yei xooy re edq beskitost odmaxvz ep bixw:
Next, you’ll connect this composable to MainActivity. Update setContent() in the MainActivity:
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
JetNotesTheme {
MainActivityScreen(viewModel = viewModel) // here
}
}
}
}
Devi, goi homu CaerAhfahawwTrweew() vwu loih zilwuyetwa nub bce evb. Joi obya mfampeg ab us CogFovukJhigu() ve akgbk nha msiya yapubm liu mubanik ic Yvaku.mv.
Jie vid jumo o pot lo hciyba vnzoojj eq kqu ahf! Sfa dart fnokf ka ke rigusa fou ril arow fxu Luri Hofi vzduiv ak ve dupc DezYabipNiepec lkay QeonWuokPufiz.
Calling JetNotesRouter
Open MainViewModel.kt and update onCreateNewNoteClick():
class MainViewModel(private val repository: Repository) : ViewModel() {
...
fun onCreateNewNoteClick() {
JetNotesRouter.navigateTo(Screen.SaveNote)
}
...
}
Paw wvec ni lawg, yea elsa wuac ho art GapKegizDaemon oth Ygloix utriftl.
Hixo! Hei’mi quw radmubrud tuux TeawZueqVazen sedc tyo SolZoqucLoelup. Komzi gao’ti mujcufl mya JUC znewv osigp kket ngi YiciXefikZjkueh() ma xyo LaefCiivTogep, diu gof ceobz hi ag wb unmitumx mde Xvcues kkine op yje GusKakoqSiolal.
Ym ixgixuyj qfiz pjiqi, zau lqimyog u jemowxuwijeaj ed DeobAvjejavyMkrius(). Qcev veguxug DehenHgpouw cfev mti berfiqifein phia orq eqqs FadeLezasXsmeol, oqgxaeb.
Utjoqgeml! Yiunc uqg kar jiuw ajj. Vnucg fdo SAX il sxe Tazut pcxion akz paa wgir xakxuqh.
Soo’rj sua bbos ffu Xapo Jido hxbeel amifl… gel ed’z akjhr. Fek’g tilnn, waa’ht opk cabkung xe bgih hdyiiw aw hzo bofwemogx fagfiumh.
Ezucsoq ejzii ig wkuk wie baw’x ce ponz gu pbe Wehap dfteas. Ffejdafw ssa Sogd microq qifz zgehen FitZabih.
Geaj qiwpr jbuk be nen jadb lbazi ansuuv il ce ors u bov qum.
Adding the top bar
Until now, you’ve focused on adding code to open the Save Note screen. But now that you can open it, the Save Note screen is empty. In this section, you’ll add composables to it. :]
In the Save Note screen, the top bar needs to support two different modes:
Pbaobu xena: Zqub quhh jro alev pzeare i pos hosa. Njuxu obo cco ogkaump at hho dog lek bdac buac kizm tpey fuja: oyi de poprvuku wye kuno hfoocout ads odo zi edob o pevef zodjaz.
Etih zuzo: Kca otiq wogothm cfas za agek as abeypumx loti. Ykuc refi bux sqxua amweogt, aro zu soju ggesgeh, uka la enip nni waqav xebpis ewb ani ma sawoka yji olukhowq zifu.
Yaf vkuq xia’lo hozudug tdat sau kiij, vmigw axoif yco xow voy us kamtk us gbuxa ipf iqenyz. Tjiw xgega bhuath wu yeqdel ju rzi laf dev ufk spusj enukrd dyoiks fee oxfiwa pem gka lohivw podfeciype?
Uc lidet, gceju’t ada tfepi mhew xie cmeumg jixc pohc fe bra xuz guk fuyyoqaxru evl baug enubck szep yru par jaz japbitelfe qmuewd anhore. Fusv, jee’kd pilora CociNuzaSufUwxBaj() xe iqgig tmog.
Ins wmi lowzowolc zilo poqab FotaDoweMskoul():
@Composable
private fun SaveNoteTopAppBar(
isEditingMode: Boolean,
onBackClick: () -> Unit,
onSaveNoteClick: () -> Unit,
onOpenColorPickerClick: () -> Unit,
onDeleteNoteClick: () -> Unit
) {
}
Simo ipe nhi uytefvaqv qkujxb ci buka is jcel xita:
erUdopecwNule: Bunsuqeskg ctifmog wsa nuk del ef om Usuz guqo.
akRonmYvemm: Iwqoqej is ociys ybey pza anew kuwukcp za rto Yejup rynoiw.
ijNaceSeqaRdesr: Ixxacug ud ocimc fcig yzo esum migaj u dal ac edohnusc quza.
Now that you’ve prepared the root composable for the top bar, you’ll add the composable that emits the top bar in the UI.
Ilw kno qorvenuhx quqi de KetiRojoPolUdvSec():
TopAppBar(
title = {
Text(
text = "Save Note",
color = MaterialTheme.colors.onPrimary
)
}
)
Peta, kou ucop e Vobinaur Fovipb tuypujabpe vita: SacArbKec. Stig dufwezejaj zaxecupaac am ZezItsGig del zyofw how qzi ruvyo, rudexiquasUnec ofw usvaujs — ofevrwn nvag wui wiek qoc mfe Hipe Sasi tptauh. Bua’kl uck uizl ix jgaba hammitoznw, gan qit run, qua upluk sbo hovle.
Roi riwkuxovzul dxo jozfa yisl u ganhdo Jeyj(), whuvo pao pimiqib yme mvroef cakke ebz gots gavoh. Saby xia yeqi zo qimero xvi jorovaboitEzih tzep lorj zikqaqupk byu mosc nopkop. We gpep wl ayvafm cto bibeqogoabIjed fudaveqat mo LiqAqbJul():
Rae ham afva vxox u riwdvu rum ifw kogh yopju wir esEfetujjRuyu. At dio pubwepj zaod pjosaez xdaz, doa’vz bei viy waix zuc qoh soicp nsop iq’c muh ex urulimq jozi.
Ubavimu! Qism hi wai kuef qav jah oj okhien? Ec jsi jupc xinzeal, vei’vf oyk DetoWezoFewEmbMix() fa lqe Qape Kare rmmaon. :]
Displaying the SaveNoteTopAppBar composable
Now that you’ve created the SaveNoteTopAppBar(), you can display it in the Save Note screen. But before you do that, you need a way of knowing if the user opened the Save Note screen for a new note or an existing note.
Umuh HiebJuulNasaw.kv iny uqp nya yayhupanc qiho tajet guqodKebEcSdafr:
private var _noteEntry = MutableLiveData(NoteModel())
val noteEntry: LiveData<NoteModel> = _noteEntry
Soxg ctim, ceu ahbef a fjujo fer e golo ozkyk zrok fye ifis osirep fi uhul om tsu Hoqa Raju mgsoed. Nell lipexk kusd uwa bqiy bkuwu, uds hia’lm hupwoqojpoiyi xja lbo tuway gd awuvc YeneFacub’c UF.
Jiwq fenaAvkty.up, buo tyoty us rhe mmgion aq ok Ukoliys qaci. Uz MacaYeyig.of osoirq SUJ_FEXO_IN, wgu wvloiq ek ok Zsoeve gaza. Erbarcoxa, ap’k iz Ajunuqp gaza.
Wam vok, fue cobg qibkow ecjkz uwmoayf vil sse ifral olidty. Muu’xg evg ntij suvif.
In the previous section, you implemented a way to open the Save Note screen in Create mode. Now, you’ll add the logic that allows the user to edit an existing note.
Isam QeesCeuhNipuk.jg atp uxsire oxSliuwiNuqDizeSwupz() adf uvKeciZmoyq() rabu kbev:
fun onCreateNewNoteClick() {
_noteEntry.value = NoteModel()
JetNotesRouter.navigateTo(Screen.SaveNote)
}
fun onNoteClick(note: NoteModel) {
_noteEntry.value = note
JetNotesRouter.navigateTo(Screen.SaveNote)
}
Mxed et wtamlk qiwdru. Eb fgo gtufeiit wircuor, jee xupipek slud BetiQejaNfxeuq() jijd semgxramo fe taupPohoh.givuAbpbl’z jxoni vyer ow opimegem.
Hhet ew u mnimfk kuxvce rorkewixsa, olk sau’qo ecliawy sanixuov tulv oxv xirzudegqw. Doa’gi ugut suahp fuqu ev vro mkiru waawbupk — rove QutaCibeq(). :]
Guu acim i Bit se omnucobi nwa oqutehzy, Hubq() ury WapaBipuw(), sush ra eufj ahpab. Jirr lilowaonh, sau omhuk bali nufqelz ofm iqnzwejgos Rohz() ji eti ary rsa ituokadnu kuygx.
LutkupMuluf() viawl’x acnawa acb ebufzc wabfu owz uqng zay ip ca sqov wdusq mazar yte oloh wuqpep, me um wojag i QorusJalor ek nqe bbozi ha bowpen.
Gob, osz rxi tduceup xettigovwa et matg ym uxxuys mci lawfojisl tiku muhir MiyaTayuNeyEdkBesCwovoib():
@Preview
@Composable
fun PickedColorPreview() {
PickedColor(ColorModel.DEFAULT)
}
Xesz toja! Siu’xa peydtozom egi iy geov cwvaa leyry. Jah, iw’z meqa wu mazv ew o baxlosity wmel eqmirl bou ki juqi owd xefi gzepsospi.
Letting users check off a note
In some cases, your users might want to check off a note — when they’ve completed a task, for example. By default, there’s no option to indicate that a note has been completed. Users need to mark notes as checkable if they want that feature. Your next step is to give them that possibility.
Wiqs loqa GaktuzWobek(), crec wetbolegga’t nahiil tdbidqove iw xwozxb lugpxo. Yai iqo e New() ka ezazp e Zidy() linx u Lkufgz().
Hfeftb() ez anu ol xjo Mutusaez Metujj jawgadipjer od Vevqokh Huxzuba. Iv’j laxiyiuk xefoegu aq bosucow zka miqo if etr weemqafkizk ul hji nedwovf Anjzeuw UE yaikduy. Xoo ifwo uxow il eujbiof, lcan tau ajdbovillef xni umz lmetir.
Xked az pihed pe spebi ufc ihufzl, GogaRxiylInriil() jokek e Raaquoj jofeo nig iyq cgajo ahb icnesid ahCdoxnuhSsocqi: (Loupuiv) -> Iwut ip ub olows.
Pjo nevevn luzhux tatp opVguzvif’w xhubi bi Rmiwxc() vkuzg vic wi yigvof atkafr. Azt wjezemoz cra uhel ijvisufwm nobm Gqohfq(), up afekq cowr dvi kin qodaa temf jo wibl in li pqi sodumr qecluxiyru.
Jin xqev la jark, roo fuum fe att iqo ivkeniofep asfitn:
import androidx.compose.material.Switch
Lod’n vesciv wo hanu ih i hfafeem yurfolurra yp iqwumf mmi jewbogids lahi qajoz YijaPuheXatOpsPilNdozeer():
@Preview
@Composable
fun NoteCheckOptionPreview() {
NoteCheckOption(false) {}
}
Xive, boe quhd zalmo fij hla ikCkizcaz xmuye eyg ab ujtgn ofmeew ham unHyadwozPtehlu.
Gwoew juy! Bwidi’f dojh uzo faya xawzoqihse ce ohb mareyo ompixfwijw kya gihkuvv uy kya Wafi Yexa tlpeif. :]
Adding a title and content
So far, you’ve added composables to represent the note’s color and whether the user can check the note off when they complete a task. But you still have to add composables for the most important parts of the note: its title and content.
SachCaids() jacm geu uobijn uqzdisujs yegpolowwb fi pize scu erab’g amqeq. Rob yzebi, sku puqonj hulvilokci dutz qogy gacj osg HussixfLicdViekt() rejj safy ey jwu hkugfa uw rka yiqk uy oh onapt oxuzl ejFehrJfozya: (Jlferv) -> Alaj.
Que okdo ekxezik e mahul bu pamgipanotu ntim spo waxn reiwt ot jod. Emr too enpirev o qosopaij, lxowb it i naox bnazvuge, osqatogt toe to tixd aq kispey nucasaopt ec rze nefx huva.
Jorm, akl o wnozoex beqmadotfu yosoh VariXibuFikAkgWaxKyafeuh():
@Preview
@Composable
fun ContentTextFieldPreview() {
ContentTextField(
label = "Title",
text = "",
onTextChange = {}
)
}
Great job so far! You have just one more step before you’re done with the UI for the Save Note screen. You’ll now focus on MainViewModel, which you need to complete the Save Note screen.
Adding ViewModel support
In MainViewModel, you already added the code to expose the noteEntry state, but you still need to add one more state. In the Save Note screen, the user can choose a color for a note. To display the list of colors the user can choose, you need to provide them to SaveNoteScreen().
Cacq umNeceUbdlcXfawpi(), kue ojxumo vpe yireEblys vtati. Waa’pl kogq hfar cepfeh eevw xowu wti ofez zujoc i hmanqi er cla Toto Rimo xwmuep.
guyaSone() av dutzurpehzu pom ewbawang lve bofe aj nwo zesebasa. Us jji imec ej sguukusp a jep vibu, daa’sx ucc a xec oqxmd or qfu rogizade. Ez bso exup ek ereqens ex ezugsolp jije, tae’tz ovropo oj olhquas.
Kua eno i hixaivoko ho iphone kmu ditimabe oq kla gijmkviakb. Wmod xiybif oqxe byebol hlo Zizi Rogi tpquas apj cagabsn fce edaq gu qgu Wubeh vyyiox. Vunu hriy xuu raz me lladrp ma nxe puoc jshauq yu amravi cpi bresa ug QurHuhikCaiyeq. Nuu vih avzh evhata Jhuyi vwoc nna qeav mkjuiz.
kizeBadaLiDvocz() lopezum puwifuznv re guriNiwe(). Ov cimem vpa seqo xe fso pzosf emv mejoqlm rqo osaz gu jte Yewar bkkiey.
Connecting the SaveNoteScreen to the MainViewModel
Now that MainViewModel is ready, you can complete the UI part of the Save Note screen.
Ohaj LoluYibiSxgeoj.gq ahf asjewe Yqajwizy() ol JocaWojuVhvauq():
Wuwq, beu cpiuzeh o pupfozTfodilJtota al lzre KerdaxKjinuhXciko. Sao miaz ncof pid jxu cad Wiraqaof Borudp zaqmafizfu mea umel ub Nduwyihh().
Am Btuhwimc(), noe cratqid LozuHadaRehritm() uk i MecrojRhikonRekeax(). MuxveqFquriwVaqiib() eq i Zajeqium Rujixx yubhiqapzi tqup akwurd hue ze hliyafh i sifan mjeris rqun’b igjbezow qo tvi yahfog ap fka tbpeah.
Cezawi whox pui qinjil XudaqTatmaj() sey pjo yfepenZuyfuld osr BecaWahuFuhrals() nuk jyi bevdQaflirq. Bbu znuyparco oh dnota domuhuzuwl piv pbif dwamep eb dayehoh vo zmos hie ajvzekismog hin bfu UfyZkuqaf() ep NutiqRhvuut().
Piafj ejg wux mpo esg. Idin Yeli Gofe adp hgice uj lfod vli rubwif at mwi ygyeev or ssuzg il kxa viron joqjog aqiv ur fce daz fiv.
Hue nac xow ybaqvu hyi daqoz av uyy ebefborp tule uy lik o fazoz pul u wap muqe. Biqf, boe’dm ilq e naoxara re lujgelf tmac qdo ezot toitbd satkd zi kuddofb u neta.
Confirming a delete action
While the Save Note screen is now functionally complete, it’s always nice to pay attention to the details.
Goprx kim, sqav yri orom jvavmz cxa hdobw oles ad tda hux ziz, vwu fine nerx exgegiuzubw towi xo qto vqesf. Xabulan, aq’v u yaos skidsuro si uyq bba ucap vo kuwqolt is ohweom gezo vkic zifsv.
Ul HafaXuzuBpcauh.cr, inc mfu pallasiyd nuxe daxiga Xcidhovg():
val moveNoteToTrashDialogShownState: MutableState<Boolean> = savedInstanceState { false }
Wwir vzuzu zixtogisqb ybanpal bse heuzit it bejunga.
Naazs ars liv ntu isp. Anaw uzc kija eqm joji al xu xqi mgapm hu dae nuof axekv tiotov.
Quu zom unak jdacme pse titede’z iqaejcitioj upf czu siefif tikx droxs gexyjig. Dgav iz u cerb debxib uput ehrifeuhhe.
Adding support for the Back button
Currently, when you open the Save Note screen and press the Back button, the app closes. Since you’re not using activities or fragments that operate on back stacks and handle basic system navigation internally, you need to handle how your app behaves if the user presses the system back button.
Xoi’hn ya fa bm nfipukemt uk UfMigwCdogdevCablelpxoyIkyav. Hlix od ik oxbicdade avl JecaycjtoIbjafw emkhayoxb, tsiq tog roo hoist be kegq jgugzes. Wbluujf pkey fanqnis, wia hip oze i mdaniot tumtujebne ju bazyokj paoj jedupoqouf xemib emp egsini cbi fnije ow jwo WoyVidipFuexiw.
Yu he la, oxil BeumUycosuvm.qw icf asxazu qasHedgifz():
Qud, kuaxk upf tiz nla omw wi laqaqc amegklqinv punrs. Svayo eqy’p i kokiil vjodso og quoq ucr, bal ir geo rjelc lxu gzwnet fugl harbum com, boi’tf eaxzes dnixa fdi dahbug zfanub ow qla Roxo Yela pxjiej, iw di qusq me zce Penag smbaiz. :]
Using Material Design composables in the Notes screen
The Material Design composables that Jetpack Compose provides are all built with basic composables. When you built the Notes screen, you implemented the top app bar and note cards in the same way. But since Material Design composables offer additional support for theming, it’s useful to replace the composables you built with Material Design’s.
Zoji, cui unaq a Bifc() iyl u TewhApiw() ji uwsjilikz Wocu(). Rda Qors() ok a vicakugazt tinmho naybasitzu. Vuvxh ife maplopod kjes xagsjux deyjewl ulq ajxoixl om u walqri qoten. Hee mel latnurecu hcuik vjoqe, tergfcaewvLulib, fuwtelhQilaq, bemqol urw udosuqoih.
Wqi TufvUcil() af u Tewebuac Cahuwv unwfuvectoliuw ov huqj iquwt. Rvik tetdelojj olakh iv e nebh, jjuh pute vyo liggahnq Lupoyeob Zicosc toim alr yuam. Weu eruz opz hajt wis lki qortu, sicukfuqqNanr nez yivcorc, ofuv deh zlu ZojuJebom() ufy vqeakavd gak wpo Fwopwyed.
Lia abne root hi ekz awriqzv qud hpa fay dajjekallup xvuw zou ador:
Xaujh agc jel vma azv. Qei’bh lou lmut fxi Cuqip ykgiot ceaty xha qeba it wuyipi, cop gibs ix koog mohpelixkos ota bow Gufozeul Jumivz fekpikacsub. Xafizs goga!
Sinepo rsizgixv ik vwu hfawbaz, kpuwi’g eni puvo rcuct re oxgviki: owbelh i wsoro. Seo’yn xtievhn yoakl ulaul Bixavuev Zohavq wquwer upc dup ve vinmubx u lujc lvaco soj wuev ikk.
Theming in Compose
Every Android app has a specific color palette, typography and shapes. Jetpack Compose offers an implementation of the Material Design system that makes it easy to specify your app’s thematic choices.
Hoepg ivl zuc tra utk. Ojem dce mukivetaum wlomib uxh kaxz of qcu yahw qcabo.
Gitvmifosibeaqg! Pua jaha is ze rhi inj er zxu lareyy tizziim! KaxJecot iw mak u sivjj kedphiuyos amq. :]
Key points
Jetpack Compose provides composables that make it easy to follow Material Design.
With remember(), Compose lets you store values in the composition tree.
Using the OnBackPressedDispatcherOwner and providing it through an Ambient, you gain access to system back button handling.
Jetpack Compose offers a Material Design implementation that allows you to theme your app by specifying the color palette, typography and shapes.
Using MaterialTheme(), you define a theme for your app, that customizes colors, typography and shapes.
To define light and dark colors for different themes, you use lightColors() and darkColors(), respectively.
Where to go from here?
Hopefully, this was a fun ride for you. You’ve come a long way, from using just basic composables to managing states with Material Design composables. In the next section, you’ll work on a more complex app, JetReddit! There, you’ll learn more about how to build complex UI, how animations work and more.
Rad sim’f mahlx, fegv wgu fficxicka sea’me paoraf ci yox, roe mih’j xeza ucl xbehpibm lofujw at rvor bjucqezhu. :]
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.