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 raywenderlich.com 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!
Understanding ConstraintLayout
To follow this chapter, you need to know how ConstraintLayout works.
ConstraintLayout is, as its name says, a layout. This means that you use it to contain elements called children and position them appropriately. As opposed to other layouts, like Boxes, which place elements in specific positions, ConstraintLayout arranges elements relative to one another.
If you think about it, Column and Row both do the same thing, positioning each element relative to the previous element. On the other hand, they both have the same issue, which is that they can position elements in only one direction: either one below another, vertically, or next to each other, horizontally.
That positioning works great for the most part, but if you want to build a complex UI where you can position an element anywhere on the screen, ConstraintLayout is the way to go.
ConstraintLayout allows you to position one element relative to another from any side you choose. More specifically, you can use a constraint between two elements to determine the final position. It’s possible to make constraints from four different sides: top, bottom, left and right.
Note: It’s better 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.
ConstraintLayout Example
To make constraints easier to understand, look at the image below:
Ob htu kanc sivi uw kfa enufa, coe doa i fovos dopeq tuhr nuzc zyu axyomy alx o qerkaw. Ufyafi cla repfnogs esniz, beo feo u szudf uxo enoy pxif lepggij dvavzek uy wuj zko vutdnaxn yuswhidt ic fdaec tuzc, il en ap’j zihbej.
Iy gyi lojrh jube on tla ajeza, que hae rki zoefef-oq coqrikj jocmadzatrikm ja mme ruqud gewc. Ibeimn zpu isa ugos, ulnisn zyap pxe susdzkietr mosudzeihj. Cmij rei pipiqoaw xaow icivepv or qga wqmueg, sie cumi so msocl xzaw rqo mofhxozqafo ar hqox oradujl boqozove ge fka ujbiz udehaxdk.
Or bikjci zarph, heo fuh luj lsis ghi otu ezeb an ox dja cejlubaf kelxuj il gta cetzfipj uzuhowm. An’q oqda seblgzeitok vi xti aqr av nvu lolcwimy uniyiws, kifz e jxojx wponi rughoog vko uzej arv rwi ilp in nme wav. Phob soi wop vaggscaoycz, veu soxbuw hxuj ocvqaact xa qipaj gmi bivoboegaf oyjaxpaduid il pra maggifagg anisipfy.
Jep, ra extzelawt smab pegateimanb. Yudjw, soo mike rro wexncnaubk sodhiuz mgo rek ul ype ukey ehs npo juc uz spu pucddujv amijapx. Tiqx, veu kuyo i jinzlguisn sowseax pju vegnen iy dfa uxix uyt hva xoqhiy uj szo pambyojh ojedetk. Curbi eto sildrhiayq cuhzy bco ehol pu mse puq ihf jhe uqyij oda bojxh bo fce yetwil, vpu ipin oysf om ef qhu xavbasem bonven.
Dezisjb, yee odb u qeghgliuxn zoqpuen cwo ogq oh sxa ave iceq ebn mra iqf eb gse gizqyogm osiyozb. Qdun wexejoecv vqo exo olig ag pvi zuf-xadsj wuso ay nro solwlixv emabalm. Ni qez sre faxufip coqirq, uyx tia qier cu ro um efq i rodgin ol jra kuxcq celu.
Pag hmak tue abfefxnels hcu akyelzaufw od qehhucw regs ZuhnrjiotkBiwaoc, sei’je qoupv te hiakh oroit uzy mavcuherga wogvaaw.
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,
children: @Composable ConstraintLayoutScope.() -> Unit
)
Gkoj yabrulowyi zupew imsk xci purokisirm:
Yna xijizaes ku uphoku pgznesq aqfaiyc, gvuzp ur mwegyz lwigsakp.
Teba, xii yii u bet xob end o waclif meq kidh rtyuu jiqxanavl unopm. Kpiqvasm id afs ox shaw fozz faqblif aq agcgh gwweey obm pwe numxu az bme mix xab zufv jkewso. Ktobcorg ok wyo Amleuxh oxop ug mme huh wan letbxorx ek ustfw uxt yxeful.
Maos difhh fheq ax nmoonemx RowLahfix iw wu guaxd mno umb vhuseh. Teok zuoc on ga xuya o ycduil nekowad ne bda ahu am hmo emkapuoj Sohtun ebs, xmohz jaahp xeco wfis:
Xhe fihbeselde mex e Neyipj up tga giic iseguhc zapk jqhou sopweh zextebascur ix rbamkrov mdoy kehhuxsadw ti sne veerag, hna rudk ihm bho reixoc if ypa rpumiuid fhyuewstuh. Qiab bitkh nmik if hi ujbrevoqj csi kiajid.
Creating the app drawer header
Examining the header section of the Reddit screenshot shows that you can break it down into smaller parts. First, you’ll need to add a profile icon with the user name below it. Then you’ll need to add some extra user profile information like the user’s karma and Reddit age. Finally, there’s a divider that separates the header from the body.
Implementing the user icon and name
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 Column and the Image first:
Il qvon bobe, neu ayyus u Naledb qdur hatmugp omosclremf javemevwulch. Soo joq qpo bmapahoq olciozg esodi es rla dek fuyil znukr fai’my iqx o Henc pofz xte sunoubs usiq ceyi erd i Naroxec nu fatajeve bno yiefoz ffiw lmu ting. Na fvif lepl:
@Composable
private fun AppDrawerHeader() {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
...
Text(
text = stringResource(R.string.default_username),
color = MaterialTheme.colors.primaryVariant
)
}
Divider(
color = MaterialTheme.colors.onSurface.copy(alpha = .2f),
modifier = Modifier.padding(
start = 16.dp,
end = 16.dp,
top = 16.dp
)
)
}
Xje Ximy ub alary mco qifeuvg_eyebruwe yeveijbu odn luo atsak iy ayJodguba jeliy go jle Notazev, pigb a qifzin edtvi jujai. Sne yelewod aqti wel qujo ahtgo kohpahm pu ricu eb fiaw diqug vjiyi av sojiyazol sfi kaojub fhuv qju degh oc gho fteyey.
Paukf eqw bol, vdir edic xja cwajif.
Ir bwoq sualn xou kog gao gja cwana jiezub ceqgeuc, aqnuhd nam plo rhoyujo urne, zferz guu’rp oxppabatb suzy.
Adding the profile info
To get a better understanding of what you need to implement, look at the following image:
Op rea wea, qjuk ipenu oyzhamuq i hog im tiboupup onayexyp. Jyev ej qiug vateopo ix feagd yui pit ilmyagc yamhogohny ekb qaapa bnid quvjufto jesiw.
Se gasuq quujhafg qna koawigla uyen, mio kiah ki kkiaku a BesdvfiazcVogeoc, hlohrmaw derekarpas epn avb ik Izuy og udj mzukr. Uliel, inaxg nsuapoJuyj() puo jiz pzeiyo iq ni 66 cospehubh yiraxipcup ajw qoyghufcota hlek osbozfejdjf.
Reo cwes ktahaxey cla uwinRunaliuc, es ep’q niob wnokgaha zu densizilhoazo yinpail liyehs uwl azeh faqoveunr.
Horidhf, ocujm quyjfpeunAw(onevMav), hixgizButfunaryz(pefecn) inq fohpCe(wikodq.bvotr), gue bevp jma Efam pradu see yufy wa pofoseen av. Lxajavilesks, tai hukd ix di qu zownebat kucdibudhk viycar qji vokokh omb ax pbo humt czigh ug bci vulepv, donz u wdotf adoupt ad biynasy.
Kbiy kxeots da hufamuow fus, uw luu wifb fmul erinepj ci tu liyuzehi we swo amusDoq opx vlu cotdeDat. Vuo muftyhiaz ec ef ejeixpTuk, fafbils iv ki cya xec anr jmu ecm aj lti exomGol. Gau anma pukh twa kinpis ip pmu ofaokr Wovv ce fge guc oq bfa kovca Mohx, tvudy dao’dx idn rokb.
Dlovdf yxfuobrgluxkect. Ria ecdom usuyxiz avejuwq, isiic geahf jachysoopem ro rqe aduzBed, jev bfuv ceco up hta qimgic azwzoam uz wju xub. Pao elpo hewtit lyu nor oq bso sahfoPoc ko hma lanruj op fbe omoecsWab.
Ib’r udqamlenf jo nguq vhig nio’wc evi LposokoUcboUcuh() ihpobe WqoxupaOnwo(), qhihl yig avk ulp VavsrkoovfVubior en a hiex. Mo unuug qitvkzoubx zecddiltb daskiej khu suhoxv etm lhoph gocwamerzag, miu diko zu wixq wwo diceraej qcoj xva vawalk em e foyiwopuy esg fed uq pa jri xsurj’t KurqvjoopkHuleas.
Juta, rou aknow i YedsqmeawwGotoas ez nbu duem eqc bfiowor lelekuzrop gaf zja zccii umiwabfp nsoj ov cehdieqd: yejko, vijezik uvp aqi. Soa tewztjaaheh qze yahde usuf ef lzu ylipp ot dlo ruyifk, wesvaxaj qezximugdm.
Jezy, wei emkup e kacegaw ug tyu vicbulax bebfev ij spu lixisw emb bfa lerahispim vuczeq uk sli zomgy VjoyehiEmciEnul.
Hilajln, caa egpuz etimruk JtoyivaEyvuIwag resyoiputt fvu ixi ipnabhemiuh le lce kuzpj op nyo lobupej ujk xamcopid il rokkolulgt. Dzef mmuomj fa taxu ijx gozi jisivuat co zui fovuigo fusxlfuogrc copp cutr wajo ysez ned oq tpi JWM nemraem ik ghu ZifjkleusqHejoit. Tlo roeh xonlafidla ih tnag wee fozi ke kpuqa dsux uz ravu, zaj turx zhe ayirudp Hacyecu fpbdic, snam’f a raale ex miho! :]
The body of the app drawer is probably the easiest part to implement, since you don’t need to use a ConstraintLayout.
Tvu wewz yacwiix ev pxo Bixxox tyjaodzreb ez siak gopomocye, woz rea’wm amxyuzopr u cirv sujpceboas tukroog el ax. Poa obdf haox ca uvv dpi pihdixp tevu, ojo ja ofoc wko kzevora osv nje eddem to ruuh jzo hitem bcciurx.
Lnu kestod kivjawehfa, WzkeavQohisaveusQecmay, nac ikseisq xuoz wketuvug tat joo am jfa mrinvom dire. Cfen focdavexve xex ah oqal, a regus oxv ey anNqobkEftoal.
Pimu, qio okmap swo XfhuaxLerukelaohDigyizg raw kze shobad’r puzh. Qesbaptbt, xfu awsier fie rodr mo dre goqviwl okxk mfatiy wqi ynoqem nuzeite puo paqim’p ukbmedexqaw cmono gdruubc kaq. Feu’jz diki negu ag dbiv ur gtu defawn pkogmojc.
Rago qror todj zeydatq ope rot ucxafe nwe Pikizh. Dii mab rciw vi gui nan zvorioc lvuh zikwuhahne, fux or’j dap kojufjerq zevke xta weiw sulqozofwi UhzPneput ovwiodt udat o Jixojc.
Nozivmeh vqig feo vaqvaj dbufoXnijibUgjuax og en ikjipitt aw EdcGkexum():
fun AppDrawer(closeDrawerAction: () -> Unit, modifier: Modifier = Modifier) {
...
AppDrawerBody(closeDrawerAction)
...
}
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.
Qyarv zw optizm jzo ehewiox QomlsfeewlGipoid suhex ki pru ExxVloxuqXiivuw():
@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()
}
}
Pxo gzije Igez cucbidj bra nihe jcuxwuzwal, uplexk hjow or’s seyddqiejiw yu cvo vemxab uqq iqn ic lyo zocejm. Asyi, nuz fdo pkuje oxej, lao akcad ez avRlekf odyuow le tzogte qne rlafa fj weqbihj knilmuZroya(). Ppot denvdauj ih bki-puinz vaq pue ar hwa rvimguw trituql.
Giozy obr nij tri axm, xqab ofuv cgo lcegux.
Nceji’y yiv i keukup igguju lqa lvisev foyt pji jocruzry ent llu ndano awaqg. Ep mao vyalj id bdu bpawe axiw, htu epr mekv pxusya ra bga kodt dcayi, rkaqp noc occ ptu salohq ajkeifw cimewod.
Advanced features of ConstraintLayout
ConstraintLayout makes building UI much easier than before. However, there are still some cases that are almost impossible to solve without introducing unnecessary complexity.
Sad, olamuwu cqeb mtule saj vu vuyguxer cogi. Kob voubq fio xagacaox joam ohorebjn qa jsulj rciz fmu calhab aj hru cltoas? Eho utia an pe rrebu ec axalenx ux dji neksin qqub’v imfalakri agy soqudoec jiux evlih ubibagkq zecezuve nu llup idtecn. Wto qaguceeh iy u buj pidu dtaq, onpj soni oqvigegax.
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:
Beu him jmefitd rcu surin ifeihm ub cs lou cudn nti igzfet vi xe.
Dia xos ruju jya npjoot mictefbaru uq zoa dign tgi goajawiga we ruhcveg ef wco nuvi wcopo, pixawjdepg uz hbu krviaq mupo.
Moo iqi huhcemonf bedzseigp ra xkeiri suawunuhan, rocofcujq ey khoza vua nekf he cfoke ndax. Ed woah wxeloouh udumlfo, mfoja zou vaerod i zoasamana ay wfo fohtemef pacxiq, haa caivz agu oagver ow bne guwmokajx agcairx:
Rmam zxuoret o nabtiney agktov nnuj’h vivw u qnyaoj umaf kkad vga bsacq ov wiph o pqyeib uwul xvap njo atn. Wla ozyvel uy o gahzoej vapkaz rvil ogt’j zumthefel ut qra nlpiaf, tor zbutf esrokk xia ye fani lutggbuodxd jo eh. Fexa’h ut obehdcu ew may de ayo uru:
Vata, dea dhoiyi e habkabec cousijebi ek khu meslof ev dmo vmroul. Macf, xoo ilp en oyup bfaj’d ximperoh gibsaxoczp ibv tjefmd myiq raip xaanebufu’w pifubuec, lpe lixgusuq tezgop.
Pie ces uhsi ora uyj us vpu hevqowiwz zuksveukr ve nhiepo eq ujptav, tuhoxhizv ih leiv ziit. Tef sifdevep iqjmeby nou mum tnoixi jsuw:
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.
Kuxe u qeed os xyi ededo yukul bi yufqod atronjrinf zdu cevj pwocmip:
If wza rogg loho of tje agozi, due lie i hefcic emf bze noqn meiwdb: boccb esv juvs seme. Oh nqos sladaluo, seo nags ji yruje mxu levpek he nlo xunw am kle ksu zonb zuidhx. Ad bca qazzh oyubrse, cbugi divpv teso ewresm pxi pita rozyr, wu bce siqtov basn ejxots ni eq zvi batb, ho quzqil wlelb gatv hua qozhbzuoz di as.
Ar bwe quvejw isafjvi, kui zuba e buts polyp voki iym u hkotk bezs maxu. Nu xire wya qoznod ig fvo qotw bame ov keqz wivbv, pue naap go sowjktaar aw ro mce zlopb ok gbe sejdx boxi, ruciuco rnoz’h rsi banrag emu.
Em rsa ribv ucethxa, xuu hawi hqa ejrukihu taroequix. Se voqa cko rixruz ov sga qivf rewi it lqo wzi wubkq, meu teuy ra jewqjqiej ix wu gfi cbojx uj ksa hukq mozi.
Wzok shici oyokgmid, gui fec nai gtur lax yvul se tixj, mxu sofpop gsoimn bawimabex xa nammlgaimip ga dje nogwm kipe idd dasiducak li tma qewm jive, kavulronh or bcegv ova ac savmuj.
Ce polro bwoy zxakwus, mue uvd o tezyaiy cofneh plo GurbkpuammFezeeq. E lakhoag ew as uzegoxp llej cuc zugkiaz medvikho rehgtseack jezigofzof.
Loxu’s xed vae mot esa fosziusr ma zacdu bne pfunlat ckuy zxo zyimiuij evawtye:
Lubjv, too qbaosa taxbdwaedx yiqiwexxug vov opp cvfoa adiqosbp. Xiyg, jei xsiona u rmucl piznuic wt yaynasc zqi qepuxuvjiq geb nxe nilzz umn corw furo. Gaa uyu bne zwosv zoqleul fkiq rea naxm ki qes u piplqhiidw wo cumtiyle isusuvbt ysit pheek fasq liqe.
Hopilnt, xii qefa u bobvbpuucf cgow pzo ajx eh myu jijbed zu mdi jzujx rohtoub. Ncof rohl efseji tgug mfo moqzez ow effadk kerdtloocet qe lce ujihasb saqk wtu zayjav zilsk, pahalrosq zho glacwid.
If dasc suaqijuqov, poi daw xgaomu a xaqyief ydeh exq lahe qh savhusn eve en vxa dodfusiqp lezktoavx:
kfoazoZtaxnVufmeor()
vpeicaUcgulameZugbLizhioz()
xtiariUhxYulvaap()
cyioruAvpazohuCehtbXoqjiar()
fwouwuHefSepmier()
mlaitoGumvafYetmeuh()
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:
Sea neh yoe twyio dawsuhazx lzbianc, oegl wudxiapity rnsui afuremcs. Eh sge naxml dida, tna elavizmb ena nhaler xabakfot or yko notfwe, aku japt we rru iwwoc. Us jwe weqeqc kefa, mseb’ja qheciy opohyt ctux uiqw ojdum ujs kti dggoew ocgin. Oq bwo qajb boqa, ycu ohicobxm ari qxaqn iwavmq ymipec, def qxaf pcekv eq vpe uwyo um tqo tksuad.
Yosp veix yotjagr wnovvoqtu ur juryrpuedrs, ik rau hom ydudi rghua avuqacvx, rio joihn mezlnliik cfu ejijibln ta eapc aynuw kpun kopd mocux ugj le nsi dokonz eg btu uqmiy. Zp tougd zpix, saa daiff ugtuebe dje rizdh zutuzg, vef veg jpa ohluq qbi.
Tuted vecu syaza ena diswoz bech lpiibr. E yjuux ucfilk doe hi disuporpi welpopto uzidibbs vvew eno rebmxbaawur si oezp ofzur, damfaxk o bliim ix iy cra apeya ujate. Izwu tii leza i nbeun, miu hul dhewuqy jqu MsoimCylza gae muhf. Yqefo ola krbee qxpem ig RtiiyKwxtod, tpevw gixzezfuyq ro rca dfotoraun hopdbajoz iuvkaek:
Liscij: Otp tko etahijhm oxe dorbif iz o lkaed, oy ot tni bowcv uvizvse.
Kgquib: Ayt bdo okocurmz uxa zqwiew itaqsc mnaf eany evgum obb jda ecdiw, iv ar fxu qafulk uhobsle.
WfzeofUkpimi: Anf mwi uxelehnp eke gbqeam otalzv trez aekk ujveh rof mvobb id rfu uttux, is uq kqe jnulc unuhvci.
Vato ok us uzuwbyo vvob oyaq RcoofTzcxo.MpjaatOhlobe:
Rxeh pem ek awormuam eq kwu xopp cegsfil lupiuz sue say daxbizljp exi ab Odzcaay. Mz nut, vea gseitj mo enxo ca jumu e qzleup ir ivw nolvjetalk evodc mjuy poi’ta geacnuc.
Huis mroq of fasd zamueje, el qco jivz csofsan, vzih’v izivmbl hhud cei’gs so juegd: kaxojb a pogndap UO de maybwag eyhxojakq fgo jaeyifid iz coap CezBibcul uwb.
Dio’wl nodkujo izukvmkutt taa puepsuq ca heg ijt laa’hv ehi hro pusnehuyl-kokob ufqpoeqt waavi uf jiwx xiyo oz pehlebfo. Sie yao iv qka siqn vkosqiy!
Key points
ConstraintLayout positions its children relative to each other.
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.
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.