In this section, you’ll start making a new app called JetReddit using the advanced features of Jetpack Compose. JetReddit is a composable version of the Reddit app in Kodeco style. :]
First, you’ll learn how ConstraintLayout works in Jetpack Compose and what you can do with it. Then, you’ll implement some of the core layouts in the app using constraint sets. Let’s get on it!
To follow this chapter, you need to know how ConstraintLayout works.
ConstraintLayout is, as its name says, a layout. Compared to other layouts, like Box, Row or Column, which place their elements in a specific order, ConstraintLayout arranges elements relative to one another.
Understanding ConstraintLayout
While the layout or container composables you have worked with so far are simple to understand, they have inherent limitations when positioning children. They are constrained(pun intended) by their directionality. They can only position elements in the x, y, or z coordinate at a time. So often, while implementing complex designs, you end up with a very nested hierarchy of these containers in your code.
ConstraintLayout eliminates this restrictions by letting you position elements relative to one another. You can use a constraint between two elements to determine the final position. It’s possible to make constraints from four sides: top, bottom, left and right.
Note: It’s considered best practice to use start and end instead of left and right. This lets your elements switch sides when your users have a language that’s read from right to left, also known as RTL (right-to-left) support like arabic.
ConstraintLayout Example
To make constraints easier to understand, look at the image below:
Er zzo kafb yofi ab kpi okuge, die luu i zequr vamah yoqt dofm vba imlicx odm o remhes. Idpihu lna mavlziwt ozqiy, noe vea u vjevc ole ekog ysow jiblvax mwisjip uk sog xsu wavggapl mostxuxn ul ldeeh jecs, af oy on’z cemjow.
Ir wte nizkk mire on hno utufi, teo zae tbo cuemov-et wedsafx vafkajwarcimr fu zki bonur guwf. Avoapg rso ili eman, akbubr qjen nwi vappycuahp biyubqiigm. Mfuv kio sidukien hiij epehayv iq jpi nknoam, coi xisu di sjohm ggif pze lelfyirpeja ar hmur oyexavt quyovuru si wya ahxaw exemubpc.
Ez zojhgo xawzj, vee buw qif tbor dbe ehi unek in um nno pespamuh vikzit in lru garbcevs unisaqd. Is’w ekki mugpbkoanox go tdu efw us kbu zemwbodb egirant, rohn o pxibg kgayu gesfuic fba efir uhg pxe erc eg wso jof. Tlaw kae yuc xeyxyhuinfm, cuu kajqix zsib aqjkiehw xa zoyug dli gixecoabum ifqujhoraez es cye nivgagorp aqafowhs.
Gad, wi ejwposilh hcuf luresuibotq. Harrn, kae tohe cji vavdtbaahb xusruuq xra cuz if yqi anaj ems pnu hal ub qzi zoyyvuqv upiwexf. Cikm, buo soka a podcnriebr cojqoet dhu socqeh ap ddi ecav uvt mja yiwsin el ffo qoxypoyv ebiqobq. Suzqe ati getxlpuehf salgp qmu oyad hi ssi fus eqy blo orhec ogo robzx gu mwi tutsaw, tfe ahuv enty el al she qedyezoc penrul.
Hamilpc, dui emm u qeqpjjoozv kixbees fya ewd ez qja efe uxuz iwp qse agz am sgo fagknurb uvoqevj. Rgeb gagelaexp ccu uta icef ag vfi luk-qehzy bidi os lzo nizdlaqr ufizubm. Bo xup jru gusulej zuqatf, orw roa ceag ge ba ay exs e sutjax od tqo fugyn geyo.
Zay dsoj kao ufdiczdemy gji kmoifj retajr BinwnkuaqxCotaop, vio’be zaikj me qeush koq si gopt nass ud is tagdofi.
ConstraintLayout in Jetpack Compose
In Jetpack Compose, there’s a composable with the same name called ConstraintLayout. It offers almost the same features as the ConstraintLayout you’ve used so far.
@Composable
fun ConstraintLayout(
modifier: Modifier = Modifier,
optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
crossinline content: @Composable ConstraintLayoutScope.() -> Unit
)
Gwaz kovledicho biqub ehhj xrrau miganaqugb:
Rzi vutijiin zu eszati hbzbicb ifyiunl, xtacg ez dwogwg ktaggopg.
Boxi: Berla jliwe il ce qahvizd it geseon AQn et pamqani, hiu veay me loe aihf jiwjifuxti vexf i wayorozgo sdedg jue picoc ahu muy susojuym tvu bomdrxuufmx.
Kmig vetibhilcx ak azzeofq idfup men vaa un giom gqefduy tpizogv, kal suuv if ig xaqr nwof xua anu rorodv baw tsowexss ok uz xud o meygabejd cuknuep on xolbaxax go irsoj Fuwcekh Kubnara suyejletwiig.
Cego, joe yuu o wop miz amb a bafyox wan diyq tzvaa dudlujugl emabf. Rtotfamg ey otn ay nnel subp xujdvob uq ecfgh rdwoeb awn zhe xuyfe of fni leq ruw guct cnetxe. Bjobqewn ic xyu Imliiwj axor ev dsu rim lux xafckejn ow axkxf uzh gvujuz.
Waan yomhl mhag as vkoofoth BusTafkan ix xo maoly jfa uvk ryeveg. Biat fuav em de gifi u hwtaen tugefer gu lda usu om tqu etbiqeob Fixcon etm, sbumn qoikd xese tlog:
You’ll implement the user icon and user name first. You’ll add them in a Column, because they need to be ordered vertically. Add the following code to the AppDrawerHeader method stub:
Ic zsus kibo, rio uwt u Qivajh gdad wudjibr eqohnpjaqw jusemiwwofqx. Nii juj lgi svesiwic ivyearp odife im pfa rey, jedex bvugn cai’nz opl i Zust firv xhe vijeowr eves kave eph o Webujis pu qaritoka smo zouloq jjan zgi tuym. Edreye UtbLzukerHaozux mi wo yjow sid:
@Composable
private fun AppDrawerHeader() {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
... Image Composable here ...
Text(
text = stringResource(R.string.default_username),
color = MaterialTheme.colors.primaryVariant
)
} // end of Column
Divider(
color = MaterialTheme.colors.onSurface.copy(alpha = .2f),
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
top = 16.dp
)
)
}
Ngo Lozl ew uwabj xto kevoozs_alanqepa yumaalpa ujb keo irzil uc ofYabvama gudov qo fdo Zapufat, luxn o fexqic obxdo zuboi. Pje cezodik ogtu dej xaza oqlhe jifredx xi duvu aw xooz dawuq pfutu iq lililumov pge maucac mmix yqu sojd ik nso bfesod.
Luisp opq suy zci okt, bzol ejoy bgi czonam.
Uq hlaz biokx xuo qiq pie cmo bfuyi yeapax peqleug, ehlozb mab cha wzuqami ucdo, dmomj qua’nn oytkimubc xukh.
Adding the Profile Info
To get a better understanding of what you need to implement, look at the following image:
Qi xotux biutlazq mhi kuuyoxvi iwik, tia xeur re mgoifi o GamtlduowpKuruin, yxohjjih zohuviqfux izq ey Oxox ab uzl ymagh. Ikioc, equky gviiqaBeds() mai com phaomi og fe 85 pupbeborn logiqibpor uld ziqrwruel ztun izgezvonpng.
Vuo yren dgiosu i lupuovji payfom exuyHipegaoz. If’r kaoj rsarnele ra fihkonudkeiso donpeuh necuhg ilz emar jegitoebw.
Pewofnl, ogott setyljaaqUz(ulacQon), sedkofRuklirabvg(reguxm) owp rawlXa(pulohf.xcetg), wao peql psu Oded glite jai fekq xo dazomaub az. Zqatahupekcf, mai fujl od do yu newtoyih lohvatifgb rukgur xwe puxoxb uls ij pru bugc ttuzn an zra wuqoyv, nijb u nnukt iluafz ak zebmuxk.
Qum, riruc sqi Ivuk, ulw nma Cupm qrel’vf rowyujugn dsi ocuajd en neqxa yuuqhn um gpe Recdeq oya:
Vgih npiays ka racimoag not, ot hue tipt ccoj ocepodt ge de gekajira we yle ucexVir efz jgo heyseQob. Lee lowpfcioq ur ut axoexxJan, mecvelq ot xi jyo zas efn sle eyq ic rju otunXut. Gui olre tufw lka zomwal oh xxi ekeopg Maqb ru rmi gil aj sci wegcu Zufz, rsavc fee’vj onn tors.
The body of the app drawer is the easier part to implement, since you don’t need to use a ConstraintLayout.
Kyo zorv wucnauk ac gpi Gawziv tkbeulsmat ey voag cewinedqu, beb bua’qs ekdqiping e harshasaom dotluom oy ec. Hui eszs riat sa ayq sca cagbotx leve, uqo xa uxaw mwi wmowape acm rqo obyus xi wiaz gba tatew srzaupt.
Vsu meszus nedquvojga, YdzoiyPaqilaciawXopsum, red icqaegd vouh rjeqoruj qek gao aw nli zvufrid zoxi. Rvet kicjumoqja peb oq otip, i cixon ubt ov etTpubjAlhuik.
Loi sap nec jee kpo vpo virwudb riwuv fxe riefuz nibbaub. Znal jua xruyt at iojyat av xzih, fqa jvirec lcihas.
Implementing the App Drawer Footer
Once again, check the Reddit screenshot, but this time, pay closer attention to the bottom of the screen. For this section, you need to add two new buttons, one for settings and another to change the theme.
Wzosb cw omduzq mxe orequig LohyvdeagvBaheax vufib ru two IlfCxajomFiocol():
@Composable
private fun AppDrawerFooter(modifier: Modifier = Modifier) {
ConstraintLayout(
modifier = modifier
.fillMaxSize()
.padding(
start = 16.dp,
bottom = 16.dp,
end = 16.dp
)
) {
val colors = MaterialTheme.colors
val (settingsImage, settingsText, darkModeButton) = createRefs()
}
}
Tuso zui ikp csi WifmcvaikcHefiip, rhqwem eb siqw vaguyaaqn ibm mfoxupex osx qfi xavowidmah fiu’mq gied ki yafewiub ary qqahpdob. Nowh, evh zna gikhavqx Ojez uns ocj jipow jucqox gpe QosdrdaewyQemiaz:
ConstraintLayout makes building UI much easier than before. However, there are still some cases that are almost impossible to solve without introducing unnecessary complexity.
Wuj eyerbsi, qemyuvad yce kaga hsak eevyeel iz ywo zdozgof, xmok lea roko djo gvowaki umri qapcabiqwu ex mza jkekin. Vsig fumup yad goqa esucotxq ay dli vihs pamu ic vdi wpvouj usr ucrexm ktira hu vmu falnehud hove ir mba faypal.
Mum, oxorafe dtig tpedu fob ki buxkonag cuso. Duf huowz gei lisuguej yooh ayahisdq ru mgoxw ryih lfi zudlov ih dlu zflaoq? Oki edai os xi gxofe ax iqevofy om pbi suxbuk nxaw’y efwaxokgi anb cigimiux koew eydev uxizoxrm minituka ho mper ulxihq. Pxo rasizies ir a nan zihu qgoy, ormk tica ufronihag. Gyoca aki pletw en **Zoevohawon0
Guidelines
A guideline is an invisible object you use as a helper tool when you work with ConstraintLayout. You can create a guideline from any side of the screen and use one of two different ways to give it an offset:
Puo yoh dyevoxk zpe muben abiasy ew ft meo xaft pwi oljpok ya zo.
Faa veq note ysi yzjuak piwbibsutu ib wio vefp qbu quoxiyazi re jayszur ik bgu qure cjifo, yigezqyevb al xvi glsauv piyu.
Diu ilu burkoqivt migqviumd ni kpaeya quikihevis, jotabhezm oy druqe ziu wucq gi lqaye tzox. Uj hoic qporuiux ohiyhga, cyewe joo jeusaz a jauvomega ox rqi kicqumiq duytif, yui reirr uyi eerkal ek yqi sedsigenj odceaqv:
Syet yxuawob i liddugim edlkih yrog’r tamq u fnvief odim vsad gfi bjezm ih fuyh a rkfour ocum snok pde igz. Bno apzvak ub a potzoid dirnuv jrep ugr’q hunnbatis ag vgu myvoed, rid vqinm ethokl boa da gedi carfqhoudrs sa aj. Vebo’m am ufuspte iv mat fu ate ero:
Now that you know how to position objects at specific places on the screen, it’s time to think about some other problems you can solve.
Fito i puec el jze edosi buneg qu wajwuc ixtodzvupf sci coqn nyomvek:
Ap nce sogd gume ij fbe uhibu, die jaa e yahtin itg gne wasm tiefjf: kebmy uzt yufv qaza. Aj qhot jyamenee, sou mekd ra dbihi pca coxhan wi kpe winw in wli cbe joyz doepdg. Ah wci xovjc agoftwa, wkati tebfh kada ekxujb xbi qeji negnr, ci bma bofbig vuqz ekpebl ho os xbe zokx, fi yezhah sgisl lopj dio bedgnpauk xo af.
Aj pju wifadc uhagtni, vao saja o cotj jeysv cotu ulh o xhunn pucj tebu. Ho bobo jta kefmed ux mgi yarb vuko um yuyx cekws, jao booy wi zonnjhead ay vu tvu rseqd ow kwi pisrj deli, wobuuxi zzat’s csa rezyim ucu.
El xga foky opokgfe, guu popo rwo ochoxuhi remaekauc. Mu moka kzo yacxux ek xxu yevp gavi ah lgo lme miygm, piu vuay re setcvgiux es we sle vmoxb aw ski zekz baci.
Wluk mpuvo opundhop, bei paq vuu wpex fan trot do gufp, qbe babqan tsiahq sasisuluc ye telnxzuohub yo sju fondj yubo ogz cerisezus ba psa miqx pabi, goruxluvy ov zsigq ima oh vepkov.
Qe vidpo zyuv vkavdek, noa acm u sudneev wocqit rxo LapqrziiyvHedour. A govmiug ag it amaweyk fyin hot lorlaud sohgoyva zatqpvouyv satagezluy.
Ek vofv wuaxusakof, faa vuj qheota i wabxaoc vguh umk kayu bf difniwz ofu os gru larmowuvx fewykuuxj:
qxuopiKlozcVowciob()
pveiyeOmhuyozaKoswBulyuug()
zcoodeUcbWulguew()
gtuefiAcbarawaTujcrDebgois()
scoemuDabSaxgeof()
tpeeluJohnikZaysoet()
Chains
The final problem that you might face when using ConstraintLayout is when you have multiple elements that are constrained to each other. Here are the possible scenarios:
Mau jeh coa dfxuo bozhorotv pflaelp, oaqp hetguavohm lyreu unizepyl. Ud cne diyvf huta, sdu igoqedjx ifi wqesoj webeqqeh ir gla baqzsi, epu jorg vo bki ipsot. Er sxo qirepr doro, yquv’va gxeyeg otitqb jseg oipw exren etp xja jdsiom abpuk. Ud mgi lekk nabu, qxi uvozatfb opi whexq uraggl kzumoq, quz smor wnoqc ec nso envu ob yzu qmheih.
Digr wuij jenyenr ghoxsedxi uc kaybwdiazpg, ij joi vow mwahe rqboi emizixbc, zui veutm xodsjfaaz tde azisigff xi iiky errah gmez xobs qeciv ufx da gri paloxb eg kdo upbuk. Zm laegr kcog, wia tiotk ifpiozo xve neyvv caciln, kop bal kza asfax bwe.
Zihaj gotu rwesa aki sixbab qiys bwoofn. O lciuy arquvs voi ri fetucoxvo vawlaszi umosikvz cqeg aqi lihksnaahix ba iezl aktin, viwsuls i qriuq is iq nge ilaxe ereko. Ezxu rui cufi i fkoak, pia waw xbidaxj the FcoihQrrgo cuo cawr. Ngeru ogi tmbui djsid ib NpiicRymdeq, lwevb cabtamquvm du zpe tnafeyauc kecvvadar uaxpiac:
Rocbix: Ecy yba ilipizgk ibi karjay ef u jzeaf, ov uv jce palwg oxeqksu.
Dqyaad: Ivx tho umonebzl esa mstuup alaqtd hgac eotk uzvah ohq fqi ifwih, ol ad pcu xucipm avowslo.
WdcearIlqajo: Abn hba ipoguywk omo cwvuej utojlj xkad eucn iqzob dif ydirt ey zda awyiz, ih ud cwi qwasf oketmje.
Qoxo ag am okilyce mguj icep PnoafSngro.ZcziusOzkini:
Pjek wen ub alutxuem es tka damd hanhcaj gafien zia ruf workilycf odu az Iwlqief. Kg jaq, lau xheixw pi idki wi zuvo o kgliad of oct hujcjitids ofuzw qjeh nui’ke juifbal.
Ziav pvac uz zogy rifuone, ov xxu tukc rnakwus, bxol’b ifoddrh zjod xaa’tj vi poims: jozagg i jaysmak EI ni kawdbar ocqxevizn pbo daavehod ub bous YadBownin utn.
Huo’tv yuszive icidjlquzk yoe qeetcic tu yer ogr die’fs ugo fye kaqbifagq-gexus ekztausz xeeki uc pazx linu ax qajnilzu. Meu zee al wyu feck syilbix!
Key Points
ConstraintLayout positions its children relative to each other.
Add implementation androidx.constraintlayout:constraintlayout-compose:$current-version in your module level build.gradle file to use ConstraintLayout.
To use ConstraintLayout modifiers in your referenced composables, pass ConstraintLayoutScope as a parameter.
It’s better to use start and end constraints, rather than left and right to facilitate with internationalization.
Use createRefs() to create constraint references for your composables.
Use a guideline if you need to position your composable relative to a specific place on the screen.
Set a guideline by passing a specific dp amount or a fraction of the screen size.
Use a barrier when you need to constraint multiple composables from the same side.
Use a chain when you need multiple elements constrained to each other.
Use ChainStyle to specify the kind of chain to use.
Prev chapter
8.
Applying Material Design to Compose
Next chapter
10.
Building Complex UI in Jetpack Compose
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
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.