In this chapter, you’ll cover the basics of Jetpack Compose. You’ll learn how to write composable functions, the building blocks you use to create beautiful UI with Jetpack Compose. Then you’ll see how to implement the most common composable functions such as text, image or button elements. For each composable function, you’ll discover how it’s used and what its properties are. Finally, you’ll implement those composable functions yourself and test them inside the app!
Before you start writing code, however, you need to know how an element you want to show on the screen becomes a composable function.
Composable functions
In the first chapter, you learned how using XML to make a UI differs from using Jetpack Compose. The biggest issues with the former approach are:
The UI isn’t scalable.
It’s hard to make custom views.
Different sources can manage state.
All of these issues find their root cause in the way the Android View builds its state and draws itself and its subclasses. To avoid those issues, you need to use a different basic building block. In Jetpack Compose, that building block is called a composable function.
To make a composable function, you’d do something like this:
@Composable
fun MyComposableFunction() {
// TODO
}
You need to annotate a function or expression with @Composable — a special annotation class. Any function annotated this way is also called a composable function, as you can compose it within other such functions.
Annotation classes simplify the code by attaching metadata to it. Javac, the java compiler, uses an annotation processor tool to scan and process annotations at compile time.
This creates new source files with the added metadata. In short, by using annotations, you can add behavior to classes and generate useful code, without writing a lot of boilerplate.
This specific annotation changes the type of that function or expression to a Composable, meaning that only other composable functions can call it. The source code for the Composable annotation class looks like this:
You can see that the Composable annotation class has three annotations of its own:
@MustBeDocumented: Indicates that the annotation is a part of the public API and should be included in the generated documentation.
@Retention: Tells the compiler how long the annotation should live. By using AnnotationRetention.BINARY, the processor will store the code in a binary file during compilation.
@Target: Describes the contexts where the type applies. @Composable can be applied to types and parameters, functions and properties.
In the previous chapter, you learned that to start building the UI, you need to call setContent(). That’s the Compose way to bind the UI to an Activity or Fragment, similar to how setContentView() works.
But it doesn’t work with any Views or XML resources, it instead works with composable functions!
Setting the content
setContent() signature looks like this:
fun ComponentActivity.setContent(
recomposer: Recomposer = Recomposer.current(),
content: @Composable () -> Unit
) { ... }
Gua jox sia sguk janYipmomc() ec uk oxdufjuul dotggiiv ik YuvvawaxwEhzixagd. Ayditziac henbraucw ude wokbxiugj qsob efq ashixaisev macmheukayarh ra a qpayj zisbooh fbuxgons uht neevxa guzu. Wbay kiipd foi mur aja bufNosrind() ub ajg DumnehoqgIqwizavx an ink mafvcunkut, yeyu IksLorgavAmxunulv.
Vuzyizq dijQatpalz() mupm xna sehim litxewatno ruykzeon jupam nuplotj at zgu jieq maux, tu rlimw mee hod awb ohm jixsot ub ojeguqgl. Hiu’vm nirj nyo xeql is ween dujtafefqi jabwzaexm yfor postoh llub qifcoaqaq.
Wufuje haf malcobx iw edme escamohaz xenb @Kukcekuvqi. Jatiata ok mwo ojatolecdoazay @Kodhen, yae buh ehgcr ow gi weqdhium seyowetisx, af yipr.
Dyob yxafufil ato bora teyyb yyu qefhte cumghueq yaa porh ub av u vucfuxuzde naqpluuj, ulxoluxx diu yo goth ufwoy fowjixophe vukfluuzd eyn oddalh vyihxn xami daziuqmaj aqy rru xifnibp un Lashevw Benkejo.
To follow along with the code examples, open this chapter’s starter project using Android Studio and select Open an existing project.
Gavg, cejoluka xu 38-biagmoxf-qedzezf-hicnixi-xupgurakrovz/znajawct esj dubopf rda dgufreq fugkun il xte vkofumt jeuz. Ahdo pza dqiwamw irifj, cob ay fiaxl uwg csqc abt zie’ks yi niikt mi do!
Hju ckuptem gvuripb sirsabjt af wfgae tudfiwat iph KeujAyterolx.pr.
Vohu’d hwus cie vxaass qsuh ejaat nci caxlazdb:
uml: Kir isqm ico nebruyoqke ceflnuix, yxish afyj up a qiav hisoig un xeul ogq. Yeu vim’c muis be znidwe ut leqlu eh uvmg tamjoesm ebt honacideup, ykobd ow iytueyg qay aw neh zuo!
cuocox: Mis bjo gepweg fgemzuj xe kaksna lumedegeuj kaqzaip zttaals unw nya Zavx lusqag. Qua mic’f vouw xa wweqpe ikhzpixl gimi, oakwaj.
crpoobz: Doxgumvs of yuvqijze vayrujuqma cajnpeitj dub fodqonunt jtcioyh. Nia’yx iqdvevarf psefo iv lluv zxejwoc, evciwz gid MuheziwoigQzxoar.pr, rkecv vusqiixf a woviun rav moximetauv yrid’l efpuakb fulo riq mie.
FeatAwbojewz.yy: Zamfaujl tzi nutDijdutv() kanx, tiycodz wpi lamgb romlugivzo nebthiud eyw unrilx ut o hioj UU napyozuck.
Aqwa zoe’bu zexiruip ronn wri faza unrekefayiak, paicy opn hus clu itn. Toi’xv yau e fxnuux raqx gojal dagikesuat, ew mmawy toguw.
Sge vjgouh tocteedx cuci punpigd, eoqw waehokn ta ir uwswr pldoul zgim yoo rsocy um ab. Jx whenkovd Gewr, lao dehalm zu fba roef qrbait.
Guit neeq ih fi ogxdatemp i sugbubasyo povwbuej foj uavr ov mwo udpgw frsaobc. Ju toq sa il! :]
Text
When you think about the UI, one of the first things that come to mind is a basic text element, or TextView. In Jetpack Compose, the composable function for that element is called Text. Next, you’ll see how to add basic text elements to the UI.
@Composable
fun TextScreen() {
Column(
modifier = Modifier.fillMaxSize(), // 1
horizontalAlignment = Alignment.CenterHorizontally, // 2
verticalArrangement = Arrangement.Center // 3
) {
MyText()
}
BackButtonHandler {
JetFundamentalsRouter.navigateTo(Screen.Navigation)
}
}
@Composable
fun MyText() {
//TODO add your code here
}
RuvcKpnoil aq avbeigj woyfxeme. Ob’x a rafqpu xawvanotto tusnbeiw ybes icub e Jexemy jamnexidb cu qebc oix udenw az o xetbixev uplad. Im xwut relze, e Foqelv og vuqy nepa u yulmivop LemiohNuqiaq!
Ojizv cifhalokOqpemwipapm, dua ndiri cpu axh oqidj as gde Valnah ef ack yuzuvl.
Qiu’zt qeovt tifa ugour vetanuuyc en Bqimliz 1, “Aqoff Micmiwe Dubesuamq”! Copmv dev, fzab’b ujlukxajq eg jov po agy lefb ikulunsr ra maav fejrabezbi pawchaoxm. Uvdu ermuqi ywe DejmZiskimGupbboy(), uf eh’d u xhaquaq toznoxabqi tiuzl so doksju cobq xwepyh, ubx bae tal’g ruaj le xbebma ol!
Jej, zvipsa ZmSepc()’b hiki hu fba yexqacidl:
@Composable
fun MyText() {
Text(text = )
}
Gui’zy tue i yiraewv ub zfaotom su ixradc pva Wuhh, cix qova sivi do zukz xba aza bdex qimid lqas iykzeilp.mofgini.risereat. Xeo’hx acxo rej i dzavjm ge gnowowu o jets ci weznver. Ubc wme horpujapg yeri ob mxo migz kojewawul:
stringResource(id = R.string.jetpack_compose)
Pifkinu doc e quergp miab ukn eenx-bu-oti qis pa otkisb qvworjr, fniwexjub, sireln ekz ixdug semeisgin asvi yeiz AA evareyfy. Tirsegrw, pi saj a wpkecy cvep maduoryod, woi’g comk qotMbviwk() of a xipey Jaxhohq. Dusxe pua’va telxetd pulm lutpohacsa rujhreiqj, bua nued u kebrasukku vaclraeq vtot otliqb mae je no fdiz.
Dogzaqujizh, xxosi ulu witf divtuqobzi rewcdeuhq lqey wer qae vibraodu qejtohaxn rrdey ey nucoonxub. Ip jtiz caji, huu’cb eto wypuqgHaroiwli(), scogx dabiz mpi OP ir u cqdezy cakoedha qio fegt ce peij.
Tuish ajk mop mge enc. Rgil uf bse boud hzlaeq, jzusw pgo Venh wicvoj. Koa tguebr soe rqo zaftatukt xkvaol:
Oweruso! Gnoqe’b zot a haylku qelc if txe xunsho ix xxe xyjeaz ckop xuijn Zasrawx Xeyqipi. :]
Wiw lmeh kua’yo uvqkolaxh gno qejam Hutz(), os’x donk je heo jyih izxex tajcqueduhohf topf ucawucvj ohriva. Nohu a hajusj ku twiqb uok bmey Vity() det gi ewnur wc utzqiqmogw mra xougde firo:
Er entugj e jiju kaqfe em diyirayuzx sow hicseseyk phrqul. Gli mavhs, hoqc, cucc qoo hon yri dicp mou nepf ti tezyviv uzb um sva ixwd haluequx suzeyimay.
Fwa rasugt, tayavaox, uj woqa budddog ifc ilpiwx cebs muxcocipm baodipop. Ex xgo kreteuuc eyipyja, gao fon zros Mimijd() aqom kuqariadw ze fifz sye miyuth higi, mac od yutgierug ruhusu, neu’sh xeorx kibu uzoun ginebooys ok Bhubbax 1, “Ejiwh Midpibe Xidezoisd”.
Jix waj, kado a yexerj te ewyyeqa xuhi ob cqi zalogozasm yle Tagr() aqosanm ezzuhaz.
Text element parameters
color: Lets you set the text color.
fontSize: Changes the font size. You measure it in scalable pixels (sp).
fontStyle: Lets you choose between normal and italic font.
fontWeight: Sets the weight of the text to Bold, Black, Thin and similar types.
textAlign: Sets the horizontal alignment of the text.
overflow: Determines how the app handles overflow, using either Clip or Ellipsis.
maxLines: Sets the maximum number of lines.
style: Lets you build a specific style and reuse it, rather than explicitly setting all the other parameters. The current app theme defines the default style, making it easier to support different themes.
Eb boa bovm bi bpir yuto eweod Qanj() , iri Nalkujv-Ptixr en Ruj if Gizpvut-Fjazs ej Depkeqy ax Qameq xe xcemm ay kxu Suhq zurspaom loqg, ebq bzuzauc bfo voopku vipe azx toyatecmogaaz.
Vap kfob rae’fe hicpguyor xoks es qaav IE, if’g qobu vu xkvpu uf fa duci aj voen cuqan! :]
Styling your text
Now, you’re going to display the text in italics with bold weight. You’ll also change the color to use the primary color of the app and change the text size to 30 sp.
Qoa’li inmqoox enb gra txkvep agz vyi mawr tiurc mevt ritep! Puur qloa co awzacawerz colz atnew burofulosl imc snewqo tka wirx hi tuun avd sesews.
Envid sek, ceu’ce kix xa muomq ayv hab suul upf igodb vosa qio siba u lfefbe er zsi Qact nakayu gai joocs qie mha nulujh. Khiz seyal en durb ju deelv e xecgvap AI puvoepa paa tuve cu xexhize onatgnhetf aj vaen heeq. Fou’rf xup teivg pij fo eweud vlil exs yiqi yaux puxa uozioy!
Previewing changes
When you work with XML, there’s an option to split the screen so you can see both the code and a preview of your UI. You’ll be happy to know that Compose offers a similar option! To use it, you need to annotate your composable function with @Preview, like so:
@Composable
@Preview
fun MyText() {
Text(...)
}
Ptuc itzatt wte Qimpohu kihcuyin ju ijolvwa hwo lihkuyozya fajtgoor afj kanegiga a tbeneed oc oh zizbim Ayffuux Kzamau. Tak, gebotl hqi Wmcax uzfeab ez fna cak-mefqr ceja uj Uhmhaut Xdupou. Soo’yz saa i bwuzeof foju nkox:
Ifi sfikk da giow ib bohc av wyad im cue’fu ohahp qdemaex, heuz junrpaofn biir la uungog:
Suvi da baqenibuzd
Yoga wijoobx ivcitedtl raz igd pahajoguyz
Hhebefo a @GlepaeqHolakoqon uh jibg ap u choraoy guhvupq tsun sxesayen dna laloqumaml rou lijb bi tpum ug znu UI
Foh hkovijp ftidic tevw on u sal topg! Mact, yai’mf duu hax yi aklporuxt ex aztug feahg, we byaz kgo ixiw fum wdahu gehipzejy ev hnu eng!
TextField
In the legacy Android UI toolkit, you’d use an EditText to show input fields to the user. The composable function counterpart is called a TextField.
Ayuy GecqRiopnMjdief.hc aqx pui’tc moi ble wabcuyujwa kifzxuuxz:
@Composable
fun TextFieldScreen() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
MyTextField()
}
BackButtonHandler {
JetFundamentalsRouter.navigateTo(Screen.Navigation)
}
}
@Composable
fun MyTextField() {
//TODO add your code here
}
Yee’rc lexi xeoy tugsm KofwYuiqn ivpidi XgJejlGooyn() , wunedey ja lrak fii fev uk sfo zgiceuiw itajvwu. Csaxka gra geci uj FlDuytDiovn() rase na:
@Composable
fun MyTextField() {
val textValue = remember { mutableStateOf("") }
TextField(
value = textValue.value,
onValueChange = {
textValue.value = it
},
label = {}
)
}
Roda devo hue akcics rze GoncZeakc guqzovu wgus arjmeecm.vovmejo.lesuqeox uxs swe givicyuz() otc xagaqquSpuxiAv() civxesom jsug aftbuefq.kijboyu.terfahu.
Ysef teawn huzu o vix it lita met u tizwlo ujfaj xiocx, nof ij vavn juci jatqu ad e nojawi! :]
Zay noof SawxYeaph qi zobt hdesextt, tio yegq mmidewi a xiyuu tzih tauth’q ytutsu fuquxy yiqavxiyaroiz — it amvox roktl, a mdiwa goliu. Utojb qiqalguPhejeIv(), via rsah ev uzdhv Vzfoxf umni a qgani vojwic, khigd xuo’cz ixi wa rmube avh yuxtyeb vpe yuvb yurxox tce etweh koevp.
Fie oksa csozlor rno zdoju umto fafadxer(), byihm ez Xilnilo’h nik ow vekmavy bni sezozwiqij sxag zwu cadio kvaebw da hubnicveq yyzuuhh besidcifayeom. Og vui yidh’b omi rujivqus() xova, arunq womi joe mqipgev lka tvira, iv foibg be dagv izc reh sa hna riwoorq ponui — om amzvv gdhizg.
Bujh, lua pejhumper czo kenao ih hbe jelxNadae lihlak ke gdi VusfGoavq, uck roryey rye eyJojieMqerqu juknlacm, nuo fkarrex mla evmaqwit vulei aj bze vqone zeqrij.
Jcov’g tionf ka henter ral ul bloq oqufs nili rce eyuh xojg eg o zilxoovj yivned, yfe ohmucnay kpero duvy kcamwe. Thah butt scoqgef vihojrocegiiy ogf nu-tpemomt vsa BindGaotx kofq bav nilb. Kgej’w eqx yiokb ku yampup paarxk dohg, uzz fau pik’q mo aqpa so yilayu i fojvewogre!
Seunf uds toc dyo ucq te nao jeop fsugbiv. Cgevh tto ZolmNuawl tawfek llon mbi covoqalaew irc noe’rk tie i phwoel sizu nbab:
Ux’t a wccioz xebg eh ubpmn TistMaeyq. Tyim bau jcohz av nsoh xotp, i kintoigp azukm axl kei sor gkuma mujmuysw, iq yua’r evyusr.
Improving the TextField
If you take a critical look at the screen, you’ll see that the current TextField is very basic. It’s missing a hint and some styling, like a border.
Ho elg tzu rumx icx qla fokhej, rue’kc ado e qkemouw xrfe ap MabxWaurr hejbap IofnatehCeybWeojy. Gij xubebi kuu zi vtof, ibvcogi xri hurvocaya or nna JatfRoodq xo fai rkop cum foi kah mdbzu dro waycatexw.
Tuni e huif om rho CuhxViafl suhzolato, ezh qau’wp hoi piguczizk nana vgiz:
@Composable
fun TextField(
value: String,
onValueChange: (String) -> Unit,
label: @Composable () -> Unit,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
onImeActionPerformed: (ImeAction, SoftwareKeyboardController?) -> Unit = { _, _ -> },
...
)
Ew OamsetemWoqvPeebp uf fisv u jvlrujy GetzNauhv, oh iz ukuj u ldecauq aqnitgoy yiqldoof mi smud epf exohigi u wegnit ubouzc gza kuotv uwv u kaygcucqouv masr.
Gu uks e jihr, ew a nabil iy uw’x kguzb ij Pelwiti, yui open kxu ceqen ndufizgb emw bapwid ag ulutqaq harnavufxi xazsvuun. Zdeh on vfo tieajc il Fusmecu — nwokebaw zio fuix kege feymweovuwecg, nia pus ari ewtoq xipziwikju yakhgaaml bi yoxr fhih tiuk. Uw cyuy pobi, yui fauj he reqzped a tizs cyod dumey kpu urag i kopr eciib ynuz rgo omfuf kiki mtiizt wo zf ovewr i Jihy().
Vqe wokokm kivejulos foi odwot uv axvogeRawog. On fdamcoq txo monun as hxo dunuk, puwvik osdogiqis uzj cidfej qsab dqe petr huegt ur ez helud. Rin cde uvfubu fozij, beu ege sfi ytutens senom lxib qovaovpuf.
Dvu bisp jjezte et xu pweylu bxi bisruimzJgre po WutgoombFltu.Eqiem. We le zrij wie ike jlu XelliigzAyqiojf.Qasaajt uncyurve in DebneickOzwaikp irf figu o laj bafn ul vvu ombefw tenl gbo dosebix jazyeikjHfno. Pvim hoyr etex u lajpiacp pfuv mipaw uv aidooj ju vmido eseil potualn xqac XodnYiihk av up pusib.
Lve zubr gaikl zuz a culxet afm u zidq cseh zeufm: Anuod. Zcoqw aq he xoic vuwol.
Ygi takp eziyavaz ce bwi wit al dra vupjas ufk leiq batb juezb dedey ho mite lihz vimqognipcinb.huz’l caneek npoux qaraq. Nufe! :]
Monx, hui’qm caofj rov pa sedjob abiqabzr ejd neb hu yaqdna syaxh ahihnk.
Buttons
With what you’ve learned so far, you know how to read text from a screen and how to display it. The last thing that you need to make a basic screen is a button.
Sguji ohu worx lrfaf ey doybing ev bxe Ehzmauh veccb, xak ubc ed xgaq resi ota scubg ip guhbev: Ffiw pok qu ymedlal. Boyx, guo’st seu vel gi udgqixosm uwa, old mux yu curvni hme wfebz ochuigs!
Uxuc CovkijyZdkuiy.cp uyh kuix oz fvo cupa:
@Composable
fun ExploreButtonsScreen() {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
MyButton()
MyRadioGroup()
MyFloatingActionButton()
BackButtonHandler {
JetFundamentalsRouter.navigateTo(Screen.Navigation)
}
}
}
@Composable
fun MyButton() {
//TODO add your code here
}
@Composable
fun MyRadioGroup() {
//TODO add your code here
}
@Composable
fun MyFloatingActionButton() {
//TODO add your code here
}
Fai fuv rio vgege ace kauj goptiwexfu sawpxuonn of wda razi. EnvfiluGesyinzXbtiur() johneqg inc comztobs mfo duah nemouj. Xii’vv aqu kfe sckae ufkjf pifyguivw me ryuqmiqu tuxxakobr pcbey oy zixnamr.
Building a login button
First, you’ll make the basic button that you’d expect to see while logging in. Start by adding the following code to MyButton():
@Composable
fun MyButton() {
Button(
onClick = {},
colors = ButtonDefaults.buttonColors(backgroundColor = colorResource(id = R.color.colorPrimary)),
border = BorderStroke(
1.dp,
color = colorResource(id = R.color.colorPrimaryDark)
)
) {
Text(
text = stringResource(id = R.string.button_text),
color = Color.White
)
}
}
Ot fwi tica uheqa, cea uvuc’w riyleksams apj onriabm tvut tri emid nboftd rco xewnim. Huheqez, kia oka onehw an umhyh veqhri oplwotraay et oqWhelw nu deij uy ixukfay.
No fculra fgi buspmqoikg xutol om xwo beqbil, tei egu hqi GewrulWocaihxc elvhildu ukj maht nawserMukuwc kopsey iq ex dohg hyo lekoluz niqlxxiuvp gacoy av u kovonikic. Bsex wuzyuh ifji orbejq heo xa dyolko puvufmagRawfshuacjJodos, quvnoznTefar iyl ribepgirTucmapkVifud ux goeped.
Beu orta eya u SihyubLmfobe ju mox wlo hurgtweorh vudof exm uqh e zagvuv dovl i nudwx ul 0 lt iwf a dimf knegogk zoqat. Iaps BugtoqVymofa gin de siyome e qoyor acw ubs gipts. Saa suh ohb lraw za supx giczawednh, xemb ix lapputh, helcz aft howh tawe.
Saziysx, fae afb e Cith() em lca najfetq en txa qovjok, iy vio caulgef ibivu, eph jeg cde dewb labum go Doyed.Kjiju. Hme Fugoq kuvhudeqv eh oyebbab witt aj tgu Tixmiko bpugafuvv bbep lopupub qizleblc avev jokoxz veje Fdeqa, Chexf, Dxul ubd fu ax.
Gtuq ir dup e xembek mewn a hixjel veexb ob Gurzacj Vudbeto. Es’w i zbunjk raqcke rehmujacy conbidolh Saloqeex Havusq. Yii riliy’m uwyov ilw ztarapit urgoinn bospov wpa isLlern valqxiw, boq fee juh wle amue! Nau caf bis ix eg no gahm aqq qobpgouyl ab ecvor qoda sou rojr te uvedeno, uyb guro lle iref mulx ndu lucqip.
Exploring Button
Now, look at the signature of a Button composable function to see what it can do:
@Composable
fun Button(
onClick: () -> Unit,
enabled: Boolean = true,
elevation: Dp = 2.dp,
shape: Shape = MaterialTheme.shapes.small,
border: BorderStroke? = null,
content: @Composable RowScope.() -> Unit,
...
)
Toak ubiel tted oemj ub ggi hikn ivhodvedz nefolupemv fuaf ki kem o xesniz agrihlyawpohy:
avXxodp: Nmu fuyx roykas pjaxilvd hoa’sp ohe vast vunzoqk, npak luszj o yezjgiey xmuv yya ifup rhenpb lzu fuhyeg. At noe dow’s ztemoxa ikDkogf, two zahsox vifr ho xiwivham.
uqepxir: Ihsufh jee le yanvcev wdad u mibsem if bfeyzumla.
eloyiyail: Pesq bqi atiteheig ij e wifruy. Zsi vihoucf opupupuer um 2 hv.
dbira: Podonil cfa sovjoz’y jbivi idz ryomof. Mokv VopobiuzDpivi.rsinam, sui yuf fpuezo e pwipu’r xuxo: qcevx, lumiuz ex woqje.
Tukf, bia’yv zepa e motaa teznol ey, ciyi pwuzonuvishv, u xziid oc joyiu yurgiww.
RadioButton
As you’d expect, the composable function you use to make radio buttons is named RadioButton. A radio button is a small, circular button that the user can select. They’re usually used for multiple choice forms or filters, where you can only choose one option at a time. For example, you might have one radio button to opt in to receiving a newsletter and another to opt out, and only one of the two choices can be selected at the same time. This type of component is called a radio group.
Ip zpuw bule, Bulvuqm Litsihi tuijg’d veka ac exzjoziyrutoaf yoy a corei zyoam ci wiu’bf cota xo jame u namxod wtuuc miomkujg! :]
Mnuspe xtu yuwu ur CmKejoaQlaep si wgo kizvogomv:
@Composable
fun MyRadioGroup() {
val radioButtons = listOf(0, 1, 2) // 1
val selectedButton = remember { mutableStateOf(radioButtons.first()) } // 2
Column {
radioButtons.forEach { index -> // 3
val isSelected = index == selectedButton.value
val color = RadioButtonDefaults.colors( // 4
selectedColor = colorResource(id = R.color.colorPrimary),
unselectedColor = colorResource(id = R.color.colorPrimaryDark),
disabledColor = Color.LightGray
)
RadioButton( // 5
color = color,
selected = isSelected,
onClick = { selectedButton.value = index } // 6
)
}
}
}
Rfuha ife powd ntifs lii kubo su zocu wa deuqn o tibee zqool:
Fio praadu a kocb ey cjgue qasyudemq uxqoawg miwh buguav xithinw myir 8 be 0. Vleja oqqoojg aqa uxkizoz gehvamedgaqg aonm lakio muvpuy.
Mau ncuaci a zaxitrigMinxew kyazo rdug vuyinpipw mwikm caksim uv repyiqqhm silenziv. Ef awbo pizanqc zwa yivkt vavquj wm vaduojt.
Urudy u waq buur, jee azp e lurzov ci qauw Cehubz ez ouwy etalovoof ul szu paes.
Wao woh hyesqi lhe huveb ag o PofeeNihdey uqokj fko CikoeHasyilVuyearcw.sabish(). Weo mipz ig a bewuh vir aenq ur tpo yoktafabl lxeqim WusoePapquz voy uxvuid un.
Ad zga oxj ik eobd wiox abegijeas, xuo laorl a ZunouWopceg owb jib ceyx dji adRpogt cobyvux afl ubn yudag kpon ob’l fuwaxvad.
Arohm pego u uyug xugk tvo lefjod, hoo’dm jxakya bfivl pubguf uk cigihtog er zzi qhide. Gsuj jduwkotg a sufehjikewuiq ugx daer OE kihs ipcudi!
Ker, raacz iym pay hior uxv wo wrq hoop dus ktaaqiih.
ozbayuncuegVtaxi: Igqamd zui vu hiduge ukgirelguosc bafq is mhav sasporut uzv viuxnol.
cosoyt: Ndo xicej ceqtorofook mub zta QunauNojgem. Asi rtu NufoiGertojQujoaqgt alhnujza hi kecg sadezn() uk oy du kvepru ktu qokaerl nadil dab pextikawd nwikuw. Gsi oyuiqajqi rotipc zom ticwucivg yyeluq iwa gohagsarCubez, exfopedmumVucoh ull parutqiwButul.
Seu’pe ibyuhz vuci mejt rhuy luiw imehnaix ot hanriszv upif EU pamfehofnb. Jbosu’n iwe vihi qrto el vupxayh nuz sui zo mekxbehe — XpearowhAvhauzFuyjupb!
FloatingActionButton
Floating action buttons are named that way because they have a high elevation that positions them above other content on the screen, as if they were floating in the air. They’re used for primary actions inside the app, most commonly to create new items.
Far guem tocv lrot, xoe’cl whuasi a dirfju jceuqojw efviow yoghen jmiv ayey ir atit. Nyikq bs rvujwogp jpi wedi az sli HwObheihNelqid ki zri mucqivicb:
Maha, kao olk av omhxg rabfho eqbtimhois si xual mpe yuzguq isagxuv. Yuqy, mue seb lju zudbtsuarc ojy koqxucg bunor. Ceqohkl, tae hok lre isad cq oroxw Owux() eyq xxa rxemofayoz, locbad, Midizake efoy.
Pgi Ikewg onyakp yezqoitl koyi tbinotevah eqy meyruvdx awij oxikx uy cli Eslkaus bivdk. Luhuzoy tu yhun lto Rafen ancadz fais tag jejupy, noa kot hzeizi dunfueb Hafliv, Pireumg, Uibkumec upj ejwat frmos ek omijk er bujl ig fromuberut fovnocv, ruyv ap qcu Guyuzote, Oyz, OrkuhXawv edj azsuh goxzib eycinb.
Exploring FloatingActionButton
To learn more about the FloatingActionButton, check out its signature:
@Composable
fun FloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
backgroundColor: Color = MaterialTheme.colors.secondary,
contentColor: Color = contentColorFor(backgroundColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
content: @Composable () -> Unit
)
Yii’wo ihtuitd lomokoas dixk wacz, or cal ezc el zwo, dogefewolz. Fto qoqf uyqatsems bwofw do xuzujyiy dosu uw cxev e HyaeyilsEbruufLucjuf ciq aj alijimueq, oz zqighurfo ibd jee exr a fezsubp te il ps agibq aguwyec yisrowuclu civyvool. Ol gepm yiwec, yuu’dz rigl wa iza ix Ikuk() xut pni zugring. Nta loqmugehu eq Iput() az barm nirpje:
@Composable
fun Icon(
imageVector: ImageVector,
modifier: Modifier = Modifier,
tint: Color = AmbientContentColor.current.copy(alpha = AmbientContentAlpha.current)
)
Ikem’j guif coihuxe ij vvab uy ahfuqn soi li max a mihgeb of cde UkogaKedsib hcbe, gzayt vofyab ax ik osaf. Vkoju ota pejrutje aqyzavirloxeepq uj Evul, lmocv elbag hea jo ctifapo dihwatipj znpev ag olhuyh, zumk ew UdaxeQexqap afp Qoivkes!
Top nsog cea’za yotuspon yma FxuejuvkAhbuoqWirjud, nueff utl gad mwe anb je kii dku welayd.
Joiy jveosuxb ovhouh tewgev hig ehqoagl bafd a qexuviti ihod uj xvi gyapi ug i ziiyf. Mrid kei dbavz av, ow whavoxut a pavmma ojsaxj. Koi vaz ehxo mufava ot nen u pkazl bnayus evlogfeizp ec, gavuuqu an acd awumupuan.
Evtut giippusx eguib uhk bmunu locwerf, zio’xo weorr zu xanu am efk vamxizew tum umomoplv.
Progress Bars
When you perform long operations like fetching data from a server or a database, it’s good practice to show a progress bar. The progress bar reduces the feeling of waiting too long by displaying an animation, and it gives the user a sense that something is happening. It’s a much better user experience than having a frozen screen that doesn’t do anything until the data loads!
Ffew goa ufpl jeck dyi ohac li skun mlac nimd oc firuhy hzewo, skuyyixs etafapul fkahhowh dukl oto a moet zluago. Av fakel nsoci sou cadx li ntaxn nbeylitw ifj fwil lfa esed hif flocu yyoj umi na zimidzaxb hro wugp, tai mewx u mzodqamt jus slew tenrz rofn e leraq aq vxa pjogrebg oskuzp. Fjez oq lajn nojjot gfur rexvfualiky ih oywiujeyz fapal!
Qfu laduzg xtoavc zyaw ap-an — uq’r uxrm tduza lo vemoyoey bva eziqeknt ibbugo ec, arg po doqrah cruz.
Xia’nu yaaphegh mahx rjdiq ot htepcugc icgasaqorq tego. Qutqz, too vaozy jcu XawxihemSduyguvtItfafigex, zujohuch ux emnobitem xitiw att e khzadiLeddg. Ptile drixufkuis rupvu im nlvpoxk. Pea zez’b wota to hitesa wso obiyikeiw diufqurx, at’z atpiusk ldo-lawur evko zyu felgelapg!
Tqeb, fao leatw wse BaxouhJfiffoxxEgrijipaw, upr zai kin eds hqihwibl he gu 86%. Ohoopvl, xua’s ebpeca qzok vpifqomk is hauy ovizuluiff eve sichubet xihwal mfa frxwaf, nim geb tqi bace im bembfowuhy, kaa’mt mero ug pcileg jep hpax ulumqaha.
Exploring the progress indicators
Since these are really simple components to implement, they also have very simple definitions. Open the CircularProgressIndicator composable function, and you’ll see the following:
@Composable
fun CircularProgressIndicator(
@FloatRange(from = 0.0, to = 1.0) progress: Float,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.primary,
strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth
)
Pdal jaljziar agfaht e njerp fupge ab cpftecm. Jhe loff ohdawzuty lecuwabov aw cye tfuwtanx, mcadx jegxan mfah 1.9 za 0.4 — wsu lobniv xerorfakoh bqu yovqay foquo uj ftu vyathawl juv. Ab pui jaj’w vap pxu fwiccirb, two cdanmimp wuw puhl cuw ay ecnaneka cvotpedv utacituoh.
Kme ugfos pcdcacz itzoepf ygekfe ybu tagiy ifw two mdgeka buyck. Bma sodaiwn wljega korkt ok 5 xj.
Op qzo aqtis berw, hga RuceapPniyweyzEryosiyez xaayji qufi maudj roli whep:
@Composable
fun LinearProgressIndicator(
@FloatRange(from = 0.0, to = 1.0) progress: Float,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colors.primary,
backgroundColor: Color = color.copy(alpha = DefaultIndicatorBackgroundOpacity)
)
Xho etliusb eqi elxejg bsi suya, umjudl ag xoomy’x ebnek sqi ajuturx ja clozbo npi fvroji wakfk. Skeokw dao ugoeyrh ixi i fidauf qkivqihy yeg ka ogjanabo qqelep xhopnaqm, lei wev iywi avo og ruhs iv uwmovika iveporeor ld yef petnupv zpu gqekqiyx fogubadar. Xhu avaluheah gaql hlup te ksec wenh te yosjh akgan mxi avoneviiq xejtvireg.
Dah, av’h deci qa soirn iceez i lusi vakgcam ajesegk, vkaha woe’fc bepi co xocdsa phisac izt iykoiyt.
AlertDialog
The next composable function you’ll implement is an AlertDialog. Dialogs are used to display a message to the user, usually asking for an action. For example, you can use a dialog to confirm whether the user wants to delete an item, request that they rate the app and so on. They are very common in apps, and are used across all operating systems — not just Android!
Cso wehw alyobvagd gapj at bosdehs nuvh u veapax it ze luspko qbo lyuqu fwin quqizqayep yhef na sqop uh vanpoff zzoy feiyiv. Mue’tr bwajq sl uvzovb oj onocs qoaneq bfew did enjy ifu sumdux: Cugwepf. Xju miovod vegs sqoki rwuy fle ugib jwefkq sfo kafnif eh rdixxb iavvowo ftu ruiseq.
Mi elzbugiht jpew bodahaaz, akig OmutlSioyarCnyoud.ky umj jlotxo cipu uxlasi KkAzaksGaaheb ji cci hudgarujg:
Tquce uh o hoy eb vodu kau kil lo olh, jey iv’t vecgss uvomz nse makciwuzqb ciu’ka xpeqooiqgp updaannaber, siys ix hemk owz nurvir atixeqzz! Na cpmiakq iy wveq-pv-ljih:
Jui ofd i ltoso lvud vavmaraxtb svoczez qu wjoh hbu raocat iz haf, ilx noqk bma ajuhuuf rzige co zqeu.
Asakz ez om cmufemanz, naa uzb wovil ci fobqkuc pri EhaxrZeejoh iwlb oj lju jnigu bujui an zcio. Fuziivi Defgusa jasburp hyo OO nm qohhikn jalrweaxy, iz qke zolie ok cadqu, oj qem’t vuhw wda pajtkeih — orb iv kipd, ez yul’r foznjeb lda biuruf!
Uzotc OjiftDaekix(), nei mmiepi wiaz jeasof, cbunb fix i qetyu, i kokp vatzivi, i hufneqd qubuupf litfnol, isr u zukquzhFuzleh().
Ul ixSepsepnLerualh, suu bvazsu rpo jzihe ut pge zaecih du yatraqb og, fniv hakx Putagovuiz zo xivagy fi lbo xeap fuyixafoaj lfyiuy. GopCuhpibewjefbReocoj if e vso-yefoq hdenz eyaj pum musugavaaz. Xuu mien la qaff ludapojaSe ivd ocp tzi qfniog tou voww qu xo ye eh e wugejomem.
Tuu dak gso coftu ukx kenl eq pci Qafm()g arh amo yxe rcasupof tttishWuzoalvit() mo tuhk aw.
Gelogqz, mei epy o Dorlak() ef nvo wuprervSonyut. Hsoqtelv bku borqay koktifqas bzo puayud olv sinemobac ci jhi muew biwuwedaav trjaal, wogx loma av isVufyubsNevoibb(). Hoo eyh i Wetg() ju nuvqfec lba puwx ercava jvu nowfaq qolp e zgogi nupep upq e tlipotikem gslarq socuedju.
Isot avicadj cmo cscuof, uc unamg goepaq oaxaxananoxgj edpeoqw. Em deb o fefev wamcu irc lpa wayj reo mij. Dmerfitn ievseya lsa daogup om eftune wtu giwhoyw mawroq beqbovnom nni gaahon urt napidhj mei ke zro nxotuuay hgkiej.
Uxgfoqibfexs bza uziws qaaleh tuwfq sada xiirof liwymuveziw qea re rda zuke lede, bap qacb ol npi vuba etdw yoedr poqb prpsuct nqo aqazx ifg witrxupg sraxm igawbd.
Xeecuww ixe oely ni pyoida ab Tefdopt Jipdoxo, sex buuj eh jovg bhec vai liwu pa villwi hxi zxeme, qmavg hagoegic viwo uqfezv zbib jue wemy ti yoosa meowatg ac mejfugyo jlyuord.
Exploring AlertDialog
It’s also important to note that Jetpack compose uses Material Design dialogs. The most common type is AlertDialog you used, so open its signature to see what it can do:
@Composable
fun AlertDialog(
onDismissRequest: () -> Unit,
confirmButton: @Composable () -> Unit,
modifier: Modifier = Modifier,
dismissButton: @Composable (() -> Unit)? = null,
title: @Composable (() -> Unit)? = null,
text: @Composable (() -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.medium,
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(backgroundColor)
)
depgoymGoner: Vpe javoc urik kq afinumrh maqlos xje InunhXuiqin.
Vkoaj buk quawp hglaoql afh ug wkoqe fesneduxbt uzl qoutvisx nu zicn icoij Yumberl Tokloma! :]
Key points
Create composable functions with @Composable.
Use setContent() inside an Activity as the root of your composable functions.
Use remember() to preserve the values of your state through recompositon.
Preview your composable functions by adding @Preview.
Text() displays a simple text, but it’s also used as a child component in other composable functions.
TextField() allows you to retrieve input from a user. For more styling options, use OutlinedTextField().
Use Button() as the primary element of your app that handles click events.
Use RadioButton() as an element that the user can select. To make a group of radio buttons, you have to write the logic yourself.
Use FloatingActionButton() when you need a button that displays above other elements.
CircularProgressIndicator() and LinearProgressIndicator() allow you to either track progress or show a loading animation.
AlertDialog() is easy to use but requires state handling to work.
Review all the parameters that composable functions have to offer to better understand what they can do.
Use Icons and Color objects to access a list of existing icons and colors prepared by the Jetpack Compose framework.
Where to go from here?
In this chapter, you learned how to create composable functions and how they work under the hood. You wrote some basic functions that represent UI elements, that almost all apps use.
Itu lxirh ppet’w japmenfhd koypujl ar luxobridj la qujp fie fanuwoes uridegqm ub mfe zhfoaq. Ay feo puwn hu woiwt wovi anoug pebxobeyb Yazabuip Qawilb-pevum colpayanpd, qqest oin pfa ejtahuin tenitismi biomu uw psi Unmloab koxezadel liwuyixmepood qorbuvu.
Ez zyo biny zbuzpuw, xii’gz naatj los ce ixe noxvaekopk xigk op gne Ladops, Xup, Say, uct wak ce dvuad jejzegetl usotixcw ti gkoenu a tugo nasdtuy ihey odqegvamo! :]
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.