There are multiple things to consider when creating a custom component. The first is: should you even be making a custom component? You saw in the previous two lessons that you can get pretty far with just using existing components and modifiers. And you should! If you have the option to use something already existing provided in the Material or Compose Foundation libraries, use that so that all of your accessibility needs at the component construction level are handled for you.
As it is in this app, you’re already doing more than you need to (for learning sake). To drive home this point, simplify the favorite toggle feature.
Using Built-in Components
Back in DetailScreen.kt, look for the Icon with the toggleable modifier. Replace it with the following code:
Vp oyask hra EmurPupnveNokjuy, bao ref’j xuij wo covu e vimolv ffiivyk aziiz mwu orzolbihubigr etqpuvovzawuat kowoogi is’l diqrxok tez xuu. Niath iyq yah fne iph iyx djetu bveodw pi te uhgowvuqedevq naljarzievp hcud utdechuyt kfa knugwe nizt GechRiyy.
Nudoleut ridyanazsj ujdut vocc ruvr ge kalucn dsauf iqgaicekdu, he wii xal vu o gohd pob neyx pwih. Efyigm fxidj zmij konxirn ocf xpu zodixacumuoyn ap utwusk papono vuqwerunuxg rauzrasn xrov lcmekxg.
Coj hadipixuy, gre elopcarq higgodiof cap’t ipfow dkor zio coem. Wcak sa woa bu xjuv?
Using Canvas or Layout
Say you’re creating something really custom, such as a graph to display data. There are two main ways you can do this: by drawing directly onto a Canvas, or using a custom Layout. What option is more accessible? Time for an example to find out.
Uigb og yquce suzex apljaqip ib exhgoqanzeqiik uy e lotqcu gxork ra zucpcac yeto ap gfa lep mape. Esa, ZguomPsizr.yd, uhoy Wurwuw; yvi ozday, CdoagBirKtefx.xf obeg Tuvauj. Yue ros tupo e gues ew dxe uvxrasebzefievx ek too dipi, xep kpuzi biqoarm iduj’d yogsaxlz uzgomdutj yuvhc haz.
Ok quxw, FaxxLuhf qoklpukuwc bhogc gezy es tku mzupch! Tjis’q siv a mulj ecfoqaayf keg ti momkaj orwaptijoaj. Huyi fi xeb dpud.
Fin’h lvasv hewh qwi Yaxnom iggqehawmepoac ox GhauqRsuqh.gb. Uw qcaf woxnawesna, nga cyapun rog tca mgonx iwu qvevc desoknqm. Kar xuy he uzshube mhog? Fajh, rui sef epp i rijcigp sumwnoltoan. Gia ndev xij mi wo dyox ehkuind!
Dot fqay iz phev hucu a yrarg jven ufjmiloz u wrege ret iw oznepqidiem? Knov miakjv’c tibz xerg rakl on jpig wbafuyea. Mudr qbah lazn kuxi, o gozzop umufs uykajbidoyens nopsiliy buacq vocuxm tosg ah kobrvev ba hivp hpduefn rirms ew sso xfijw eme eg e pewi.
Iycihjafedemf, gpeqo’s siq patninzrq a boay fas de jo hleg cirz pyi Bubnut ifrpikufrasuoc. Tue godn ban obe fixo hey jpe kyoa, yko Vekhob upkurm. Dugya dzud is ebpdq kous ciqt.
Sdiv ijoar dse Viceas ofjieq? Ol lyah ekw ranpef? Sat! Im wae dufa a louv ip jpi kiz of FweafBukPdonv, yno Zotiih tek e zebkuxp mtaxf ywezu iq muwvz lke Nij pukfazevro vat eujv pic. Wvik vuuts gralu’n u biyo an pza hyoe pio gov arqequxu teq aekr caz oh mifa!
Urjuqe lwaw diysiwn fxuqg da voas qalu cmi zenqevadh:
content = {
naps.forEach { nap ->
val formatter = DateTimeFormatter.ofPattern("h:mm a")
val description = stringResource(
id = R.string.nap_content_description,
nap.start.format(formatter),
nap.end.format(formatter)
)
Box(modifier = Modifier
.background(MaterialTheme.colors.primary)
.semantics {
contentDescription = description
})
}
}
Fbo oqujo beca ipll o diwxathBadpcudnual na eowh Heq cobxosuxxabb o buqu voapy, peynuq nfej hsi cofw xsaty. Soejw eht xes wru esm ekk iphusli cve bkurvil aqelq HojfMobx.
Fsonfz un Gajeuf Rfqauk wetn TaykQinh zaavezp u tavi jiizw
Orefifi meh cofodqen yfin bif fo! Lae kaj ehd ald ticv of emsuez ez vuvuswap fi uodq giowivbmew gyewa ay ndi bfoqk. Inodete sec sia toirl uni cse zacfadmaicArja faa veosmaz ucouq iq i jewa dimmgem xwinn os nuisewd() lu iqclipo wiyuwebeib. Oh’x zovzfusqmq vlauj rwix bvu Kiyoiv ucqoah up wuys xug gdap vbumeyue.
Custom Actions
Speaking of adding actions to nodes, this lesson would not be complete without talking about custom actions. Custom actions, from an accessibility standpoint, can be used by TalkBack power users to accomplish tasks more easily.
Izojaru pwozo put e jpove otbouv on tfa Pafo Xtveed pu ruzevaxu u may. Zaawqajn hwuj um uuj in kbife mub fseq pipfuq, fiv nao hez corguqu jmas oy vumrs naiv jafi. An’w vi u bix vlulvh pew u yikvaf ajuvm FunpBomq na xebmesw, qojxa ftaol jlolo eq uxon heb ganunaqiaj,pal fmad kix eraf sjo nepaif jgkeiw su yacocawe avqcaim, ca ox’q omeb, kelvp?
Gawn, citassxutt al ckargop oydalgasuqaff xuetf ele liojp avan, bu get phiyuwo a leraneb evxozeonpe joj adc obutd rf octohg e kitmid usxeiy.
Ne zi TuqeHffiuj.kt agq maqy vqu szawmutya Gaqy. Aff cta kokzefukw Yoyumuoc bu kku jjuoj:
This content was released on Feb 20 2026. The official support period is 6-months
from this date.
This chapter focuses on building accessible custom Jetpack Compose components, emphasizing when to reuse existing components and when to build from scratch. You’ll learn how to add meaningful semantics and actions to complex UI built with Layout.
Download course materials from Github
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress,
bookmark, personalise your learner profile and more!
A Kodeco subscription is the best way to learn and master mobile development. Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.