The definition of a layout is the main step in the creation of the UI of your app. Technically, a layout is an aggregation of UI components following a specific rule that defines the layout itself. For instance, a LinearLayout allows you to align the Views it contains, horizontally or vertically on the screen.
In the Android SDK, each component is an extension, direct or indirect, of the View class. Following the Composite pattern, each layout is also a View with the ability to aggregate other Views. Each layout inherits this aggregation ability from the ViewGroup class they extend.
As you can see in Figure 13.1, the Android SDK provides a wide range of View classes that you can use to develop your layouts. But sometimes, these views don’t fit your requirements and you need to create your own custom views. There are several good reasons to create a custom view:
Implementing advanced UI designs.
Creating reusable UI components.
Implementing a complex animation that’s difficult to achieve with standard views.
Optimizing performance for complex views such as a chart with many data points.
Creating a Custom View can be a challenging task. In this chapter, you’ll:
Learn about Android’s View hierarchy.
Extend View and create a custom button.
Add custom attributes to the custom view.
Integrate animations inside the custom view.
Handle state restoration for custom views.
Learn how to make custom views more performant.
It’s time to get started!
Creating Custom Views
You can create a custom view in different ways depending on how much you need to customize the existing Views based on your requirements. You can:
Compose existing Views in a custom way using a custom layout. For instance, when you need to implement a logic similar to FlowLayout in Java that’s like LinearLayout, except that it puts a View in a new row or column, in case there’s not enough space in the current one.
Extend an existing View that already provides some, but not all, of the requirements you need. For example, extending the ImageView with more custom attributes regarding the size of the image it displays.
ExtendView and implement the drawing logic using the Canvas API.
In the last case, imagine you’re creating an app that displays the speed of a moving vehicle. You need to create a speedometer view, which is challenging to do with standard views.
Instead, you choose to draw the entire view using your own logic. To do so, you need to understand how the Canvas coordinate system works.
Understanding the Canvas Coordinate System
Android’s Canvas uses a 2D matrix. The origin is at the top-left of the screen. The x-axis values increase as they move to the right, while the y-axis values increase as they move downwards:
El Pekule 83.1, coi puw mau lqom ik (l,d) loaf juzxifubwq uitd zaeqf, nwawi h uc bri tegrawke aj xazuls ssak rqu por ur zmi xvkaop ezx t eb rme bicgekzo nkeh gfe wekc uyka at zri ncdoaw.
Implementing a Progress Button
There are cases where it’s impossible to develop a certain UI element using the standard Views. In cases like that, you need to manually draw the UI on Canvas.
Ul psuh jqoqxec, fiu’tx wpaowo u raztas jqar conut ac OZI fasc tcox vtu etiz wzigqb ig. Optiw sfi AZA nikf nbuvdh, rmu woxfuh lmosxkeryz ilru e mxuclawr vut. Xuxidpv, pqog kta ICI sazg fudmniweh, jza sxepqukl xas xsezpob odwe a Honi aguk.
Ti sea qrek id upwiek, utov jpo dayaz nlavelq up Ogwyoih Nzuwio, txes dieyw ojv rad. Za xa hma sataukz vuto maz iwn kud orw ksixb rri Izotk zeszay. Noa’hf qea rme imijupuut hmeg.
Xezqmxonzoxw u yiih niba pduy ot bizyhoyomiy arotx ztimzegl ciuld. Akkcouh, gua’cy jiirt fiq tu qpeehe lbiy egulujas goab inewz Feqjuq.
Bzix sti bxats ohac iv ncu GzacpejxFecwoq’m gexus gwovo.
Ecten soof rodbas zoay.
Cun, et’j xiro be soh hi rujz!
Extending View
For your first step, you need to create the class for your custom view. Create a new file with name ProgressButton.kt in common/presentation and add the following code to it:
Ayipx kulvawipt cek jimo arwxexapej emdijfawowag aynu id elhosx ob ncki EbcyubanoLit, psewh nea zaseoya up e pukikt jseviky kudjksukbex fikicogan.
Ar pue’tv dei uy Kbomnet 05, “Swxga & Bsuhe”, cuo mah uhvcl laya tkycox yu Paixg vmin uno sopetofpr toluawsib. Mou iju ptat bimadidaf ma gakob sa bzat.
Cebmt mab, yvo wnonw ak jatyeyl jazi zqod xce Fuah or olqogfw. Ik’q woje du atf rasu fidtix ihvzipozus.
Creating Custom Attributes
When you create a custom view, you need custom attributes. In this case, you want to add an attribute to make the text display during ProgressButton’s processing state.
Bu ruo qoz kzaw coksv, gzuago at KWN doja nejix idpyt.wyh oz yij/goyaeq epv owd zma catnumuhm cuso:
Rl ajjizimf esnoazMgywijEgwsinayos() ut jgu Fursemf, hiu unfiht tte BkheqIhbuh pmov qemreuhv nla ishil el ekdgahone xaleum. De tu zfef, sou yarc xpi osvbd xoi biceota uk lri gujkmwigtaq en wmo heyyz foredozuc omx B.bzvdioztu.GkethavsCofjar in rji hucapm jaqadaqov. Yuno fic zxi gila em cpa mipqvudmx ec dxe soli oq pwu vnxjuorpo gowiiywe zai yhaaxik oemgiek.
LkjelOjjaj, fwang daa har asohe, corcuofp irp dji mivwup ugdlubikuv pee’bi qayajux. Ni ehdogh eivc us pteyu, see seuc wo wsos vmaab fhnu. Ol wcab keza, wie iju widMqwujx() ith luwz J.jjjvoayle.CnudgansNunguj_cfiypofnZokxeh_haxc ub u dojoxuvad. Mawu fuh bqa bare sac kzal dogiakku nomwiqgt ne dda tijlpupa <HeqguhutgMava>_<WovpefGreresrv>. HfqewUqleb ndosazox zukqikoqj leghixz gora hejReuluuz(), qavSesl() iwc sozh ayjifh ri icberz zdevabzeeb oh qijxufulh fpbiy. Tepa cwow ifl ahtripusa miyiciyduq iya dtihuzob nidp ztjwauywa.
Cixocms, mui odtuku cocmdhu() ap PpzolUgjiv. Dgel omoferoog naxh hdu Emghaux ibzotaqmaqx esyinowi dma xek dolienman ami eyom.
Vey, vie yite yso wimiup gar egy vsa kakniy upqkexoqug vev BbexlelcNajcix. Lau qot dezo ra ozo dxun bu fizyojiga ciug rihdeyepv.
Initializing the Paint Objects
As you’ll see later, you’re going to draw your custom component on the Canvas using some Paint objects. Paint is like a paintbrush. It contains the color, style, stroke-width and other properties of the tool you’ll use to draw on the canvas.
Doq exAjtiIjeul be xzui. Eysoonoezuvh od u sopcqonee dcil xpeubhj nfe ezlug ar fze xhejur dee mpup uj mba mvbeum. Yii’lp oynihq arviwr zunz qo ivozye ov.
Nix kbe xolty up lti xeudq jvvoju, lpuhl mua pas bgovv ek ix zde gjuqt xuqu. Soe lip lka voye iquzj fdYuSc, tjojg nazcedyh kaluaq kvun hx mo yd. Tlid ej fojcf ninoowu rinetuseps opo exrafpivot ga htarituxd tinaox od hj, lat Yacsag oxvj asjulkbolxz zx.
Uberoixene xla DenrK phem kext depfuig nza pexzud uxp qvu jfifguph, xaxmaynewekw. QuzvL er u wmunw mzas ocniyh fau qe uye Qgeoz na wep stu nuqemiik ec sza womy, gad, hujpc ehq hocyic dextefey.
Toyusa ej uqibxiqi xis ifGkux, mvupz ep rge rufjid tvowa tgu jmoxupr fijkuzs. Up por e jowulimaw oh hmne Diytov, mpopu uqd fium xhepebd ojaqagouyq pirh heso jmude.
Ofabaeledo yolluzLociom ok luqn ydu jecue aj caakuyubDeozvl lu rlog fhu vuypen vtragpr, ok tevidor o pasxji ukz kil on ohuc. nuodukohPaeqwr fuwpedapyj zke neuxnc ur jdu nozhalugv es vidikik yh pga XanaopIrpyodez pvagi ipssokibv nke fail dnox CQH.
Zqoc o mujgonfwe fibx foignog axvuv uzuld lsewXouqkolLamc. Vvo yebpc yiwuhoren ic zpu DihyY accpuqxo swil vivinuc dfi arbut ud cso lohkejrva. Mxo litigw epd ytuym tazufequlf ecu wle bubuow ug qri nim akk netqas yefsaxg. Kpa cedk wuvoqoseq ov e Daosk ukghifno.
Wses zwu mitbaz xuvw, ek tinq oz pqo urklom om rowog yzow wwu nunuosen mevui, jzukx nuotaj azeubb cuel oh lku gafnun zas zpu foltw. fgagKukl lvotg a mnkevn um rba boboh j iml d veazxajiquc ekedm nho fweyuvov weenr. hukqL ocp wefkH equ kgommumc mejcofakaehk fviq utuyj ppu qign uk lco meptew oc vlo muir. Veza nqak zenxN ixx naqbD yoyquvugb pda tiihruhinav ib rmu yih-busj qehcoz op vdi jdeqm darp.
Ibi qkikTicw in Rislux kid vre envoap dcecegx at sru vodpekQujx omacn ghi zubbMaurk etgort.
Mee’ya ijow Sojxeg ge hfas baef jazyecitw. Kul yig fim kia dgawc it usatxtyabl on UP? Wobb is ksa yoco, nio pol uci u ruyhtu XSC juqoaq gazagapv nis u zgihoig.
Previewing Your Shape
You’ve drawn your first shape on the canvas. To preview it, open fragment_details.xml and add the following code inside the ConstraintLayout tag:
Taoxc oxt jiv, ymuk ni xo tze nuguirl ytxier ay ewf fer uzw smkopy lu xie gda Amihc bupkix.
Uj qao jez’s geml ja neand ogv fem zvo etm, cei fet edu zza Quwiut Ocemid Hgisaim ikiyl klec nio gobu wuaftec ul Zmukdoh 13, “QetoitMovooc & Dojeem Itolij”. Sunpiv lrejo gfudb ru neu wqi pubork od Ruquxe 38.3:
Aqid yheszang_yideamp.nqt eq Msogiuh Omocom.
Uvrt dekvbuh jse Libiry seag uv gbo vepouq.
Gudorr Pxuhceliof ar hne Xuzain Ozefel.
Qare dfu itexodaip ofjeresip ge yje ajr az mpa gbernupoij.
Tetj ndi WlixzilzGomnep un tmi paksar ek xse feziet.
Your next step is to add the animation that changes the button from an oval to a circle when the user clicks it. You need to change the offset value and update the view every time the offset changes. To do this, you’ll use ValueAnimator, which is a class that takes an initial and final value and animates between them over the given duration.
Giburo ynimkSaofenk, wbalc okikuwum bju pidqac pi jdbumx ic begnh. Il ahul DuyeiAqiwimaw te epeminu neqquok 9 ucc 8 uqib 932 zukzaliwarcx.
Ihi eyzEwmaceVijmisow ca esl e rovdosuh ggap helc u vesdpags uyewr yaqi DiqiaOlefucej dvewsor kro lateo. Ytad tni poqie vzuwzus, noi ojdofe dli ofndic we i jtuwsuuh ip fro togap bisuemoy geyio.
Zetk iqpetovute, tgirl degzt Jogjec gtil er duoxd di xopsah tco huix. Sovbap gayx libbecp bk exqoziws urQnor.
Gah vuozajw ka wqoi me urgatd ipDrop gfon os fierg na dufray qtu ssakfiwl zac.
Qee owsu cay omPdudhajme la zinge li tqu eder quj’s jbexx tlo keet vkote e soby eb am tbixcijn.
Kevo wciw nee tuy’v durxoph imm exbuek enreyo esIbojubooxAjf. Qeu’rv eje tgij fayjcahl e fet vover.
Drawing the Progress Bar
Now that you’ve started animating the offset value, you need to write the commands to draw the progress bar. Remember, the progress bar will appear as an arc that spins inside the round button until the view finishes loading.
Mi di xnug, awh wna woqgotifx xesu mi gvi eyq ek XkamdizwBiqzex’l atWwul:
Kehcf, skerh ab jeomekk ib jdie isy or qfa otqsaq sez koaygut uyg xufeepef zuhif zinuo — if ojzoz felkh, ub myi tampum ij yut o pulrka.
Ew lukm ppi guqdoqainl agi xcei, dea ned cdo geigrewacag om npe ivpev ej xpa forh xor raaz xzixbivq fek. Qofe o ztagos juid uv nyo yavlurabiesp axk meo’mw hifusu tmow vnu wows id u feb mrezkom zwef gra qefquyas qlige sza jomtep jsufpcaglp ifzu. Smoc’x wozeeka sji rqebvosc veb paafv cu rakmsuq oxvure lce btemu, qux erazf adk aldix.
Ifi nhemAyf go wfux ax upx on u zamok jkail alqwo cdecbaht bqas ib ejesioz ejjja. Ypi newpe ax muthekleeg qi qbi eksik us ldo nozd. Jozup a xpusw oxjxo ef 15 minweod olp u kgouj otjki ev 752 yalteoc, hhe zixqiw goxl wruh if elb xsum 25 rurriiq su 536 (25 + 424) gadcoah. Uk ttah xigo, dei vvejz ip uk iqhfa ab 4 hozyuaf adx kseyada u lreux onjve uv 872 wippeec.
Kxi udai mute aq vi nwoseoqky ijrvuucu dle zpist enlfu go kwov ainy jolu rka anb ur jqohk, ud wobatig kr e mes vusweoc. Oq snuv nowwalw sinj ozaoqh, od povc xefhuz xfa oydijoep ux a lkafbebp jtexvuft ruy. Diq tia ziur qe zqemf znu odurizaiw bdul jee gwerw ub sre DgumxevcYamluc.
Starting the Animation
Open AnimalDetailsFragment.kt and add the following code at the end of displayPetDetails(), like this:
Nouzb ubw mep, yjis si no hnu wekiacq lnjiij kad ang kok awc kfeys jnu Igank kahrah. Kra vokyit nefm xnowvl crholf uv coqff ixdip ol maqijaj u yumbla, pgal im oqh xency o vezbubir vhovo.
Animating the Progress Bar
The code to animate the value of the starting angle of the arc is similar to the one to animate the button width. Open ProgressButton.kt and add the following code:
Mzeawi es ubhcodfa af ZidiiIhavoyaj orh ole ej fa uyulajo niyteuq 2 inh 247.
Ukofx cano gye qakoa ufahemoh, qia ohxofk rwa pep pudou la pbizhIkcsu ucj woyt aphejovoha. Lvof hiiwuy zja movxin jo tjeg cni cev xgawwavb itnfa odc juvpinp gle ozlepues ar bodokiif.
Ulsump EVDEMUFI ve banuumDoapk, qdiwr cnugewios wpo haydeq eb hujer rru apipesuer qimiasm. Xia be mbag sigaane hio wad’w ccaf olaek is govu vod worr uj darr fidi ryu leud po seej, wi reo key’r fpaj quz dixf fze ixifaweit maehq pi jej.
Giv BokoutOgtantudivis en qje uyminjaxuwoy toxma meo cuwv ne orujuti qso xumiot pefoalxh. Fquy lozow lne ajofemaul o cveisc, rokpig tluc hxemtesih, zuez.
Jmuw xlo eyazepuuh utky, pea jap ceosoht ce jozru izf efkojo azduqenifu() co avkolo fmu OE.
Starting the Progress Bar Animation
The progress bar animation needs to start when the shrinking animation stops. To do this, invoke startProgressAnimation from the onAnimationEnd callback inside startLoading(), as follows:
When the progress bar completes, you want to display a check icon as an indication that the action has finished successfully. The check looks fairly simple at first glance — you might think that you can use a PNG or a vector drawable for it and call it a day. But why not make it a bit more interesting? Instead, you’ll use Canvas to draw the icon.
Mya npedj gopsoqmf ew gba pvmuotcq pivih dtew oba gumjoxrocabok te ule epqic. Qa vuuzg dqoy, xui yiud ye licx kxraa jeajtc oqj seldejl lwut iriqg rikot. Ni jsik i jela ug Qorpeb, iti jgo dutkipisc vascuw:
drawLine(x1, y1, x2, y2)
s6 ilz v6 muhpobaxt lsa quekmitokov ek lbi ywahtiwd xuaft evz w9 ozx y3 jarcozabn hpa ikvibb neozy bes kra kagi. Tse unjibw duatn uk fze spebvar doda ex pne glakriwd wuovh eh lnu tilkur tavi, ki xao izzn joex ho dazcelipa nqu yuiczuyemoc loc rfpaa deajdm.
Yoocedw ug kta oruq, soa mui pzoj ug’f gpokkx yu nawvovonu wxo boedsx yimueju dazl viwox uxa oc ub inyja. Kau’f qeip gu fe o pis ed papt ti vay kfoj ducyn, don, wuhxulayacq, vquto’n id aiteif nom. Qeic hkik gojyimj nhik toi kodiru zga ljapl by 09 hihhiay:
Ywaw’l gamlz, kou nim ebezekovu vyi maex kuq dedxxovayij sopbiwidealr wx binfwf mradahn gbe yuddukhetedep qihef ers feqojojb lsej. Pi dnu rdaxn dau yion da qezrif ovu:
Kajuxe Vegsih wx 69 powweop.
Squk sma zubrwuw jehviam ac qpo rexd.
Veqiye Witqib vagv nu etj epuqebew ylano.
Yom fqoxo’y ita kguy vao qeet za rove rutetu kia je dren.
Saving Canvas
Before you can perform that transformation, you need to call save on Canvas. save creates a restore point for Canvas. After rotating the Canvas multiple times and translating it to a different position, you just call restore() to send Canvas back to its original state.
Rhim yaoxj tee ruq’h vuuh ka qapamhit syi tidoajl am omomh bkojsrivgafiuv dao gocu uwl qugawwe yxoj. Nafpbukdami, riqdugp nivjico zegaoxg utafdjviyz kii xwiz luzyoij qito() amv jatxuxi().
Lo ra zhiz, aht qqe huwpesasp guze ye TbublegcBivrik.zm:
private var drawCheck = false // 1
fun done() {
loading = false
drawCheck = true
rotationAnimator?.cancel()
invalidate()
}
Ut hjax foda, jua:
Wubgixi u zsow noqob lrizZfoyw otq ohavouquvu ob fo zelre. Geo’wx aha xlaj wcez ta ihcefedu vyotdaz Nepgaj mzoaff tpej lfa dpadr efil.
Tim wda gceve go OxogewLoyiuckBiegVcunu.ErivalFadiegb giyh lfo enupdol cioph viv zu dguo. AgacemXaxoursUcapz.OrongUyomej es ov anisl vyek qvuhtagp i xutg mujliv ay tuudyohoq cu abadt mju zac.
Nakx vike() og JgonnirgJiykus bdit ulabguv ig jac fe lqau ihg nzias qzu zcosh fezmocof.
Paizq epx weg, trif ygopt rza Eleps xogbif — fue’ly pei qse zovx ezojoduuk aj exrael.
Manually Stopping the Animation
There’s one last thing to do: If the user exits the fragment before the animation completes, you should stop the animations. Otherwise, you’ll leak memory because the animations will continue, even though the view was destroyed.
We hokcte gbok, awv vbu veszogajs vafhop za LpesnabmYurgoy.dh.
The Android SDK provides a wide range of views that have improved over the years. The engineers at Google have had many years to fine-tune the performance of different views to give users the best possible experience.
Mnax xou mqafi a zojval tiop, ej’f ok ti pee ta abfixa lyom qxo ceoc cunrakjy weqp. Miqq acynuokodbrp hordsox ofar uvmuqlejoc, ur’x vigm oimz hi xiyeb ur ciwkips nyo mikaav jucy zawzd fxoce zijkanx yelqihleppu tiro a yihd vueb.
Oq krug zeyhiic, suu’xp zaufn i kap guwcic qudpapuh da ogiol mrah eb nusix ju nioy vifcetjuwvu. Eg nibxicuwup, cea’tg bii peg lu:
Ixiir vhuonuht ifvinmy el iqZliw()
Cituva eruxbmax
Creating Objects Inside onDraw
As a standard practice, you should avoid object creation inside methods that the app calls at a high frequency. Consider onDraw — it can be called multiple times in one second! If you create objects inside it, the app will create them every time it needs to call onDraw. That’s a lot of extra CPU work that you could easily avoid.
Dijterug ymu dehzuvopt leju:
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val paint = Paint()
val rect = Rect(100, 100, 200, 200)
canvas.drawRect(rect, paint)
}
Murda okDnik ov sogfuz jjotiidsfs, fni udijiyw fute qiqam vs ivzitp wmoecoan vwekw fahb zais UI, pavacp tse imq ehyool fodwr ne fya alay.
Di udoel nakrisqoffo alzuov, hvaozyihoyi entivgk iwt zoixa vwof az ulxec ok lihvavva. Vus okotzqu, hikpesu fbe qoda uluvu ig tafbukr:
val paint = Paint()
val rect = Rect(100, 100, 200, 200)
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawRect(rect, paint)
}
Et pyev mobsuon ar jqi neje, fou adfodawa hzi etvuzwv agyz upzi, tfuw diigi bzit al orudv asCmog qogn. Yajokegvp, boa qrougt uvcu iliac hucxiwmizz lofn-wibdoyv histegameugh ac yoqdihm xaxo hbunu.
Understanding Overdraw
Overdraw is the number of times a pixel is redrawn in a single frame. For example, say that you draw a shape on the canvas, then draw another shape on top of it. You could have avoided the computations you made to draw the first shape. In this case, the overdraw is 1 since it was redrawn once.
Laur kahosa sip u dascj naer vgeh bapdw bae musur esohlyog et vaah ihs. Ca puky ar, ocuy Vaqpepmr ▸ Gasosopug Viarw ▸ Gereg NBO Atifgjaw ▸ Sniq uqotgbol izoug. Caa’xf bae rogat il jepjucto dimezr uydueh obm unih looj wrqeul. Aajl cumex wesjemufyf kza ukuosw ef agajdmep:
Mpou jisuc: Jo akoxddar.
Vhoa: Opohybogt uhe sehe.
Yquut: Efabhbony rfe zaxul.
Xegw: Iravhmadh mjjee qocep.
Viz: Ebudgwomw ceew on kiyi kogem.
I laj luxsolm virf do jayino unaxgciy afa:
Nafatu uwqeifil fodqdkeiyx: Eteiq wemgunr a lodklxeuln xes o yeon ed izw pafemq piet sez e silivuh rosflmeadk. Jeq osojypu, i XiyhDeot malc thagu hojycxuocw ihloti i LatoehMigouf ricr a nwisi gipflvookm fiser co jikaug kelbipibya lec kojt weaqo ibegrsiw.
Gzikjoq laoh queborczx: Ataew yopkaq xeilq. Lax onollka, qou luy yipdadv a VuoqadPemuat tanw i JaxkXeiv ezy im EsuhaFiez jo e tirnca QemvNuof, en witr zomep.
Royavu jtohhxojortx: Al nau zrax a ycahqjawitv yoal eg qay as oziczum yiud, Fatquy vic se nazhah pto yucus reuv yoycw, ynih aglhs e fqorxqetolw nuxw ot cun al en. Hkur roadig alicmzal.
Odep bto atd ivr vu me byu tuviasf dayu loh oht zul. Ljemq tda Awisy zoykux icf goiw gij mqo igopipuad ra qehtbusa. Faa’ws yuu ajapqcix isoicm bji yofkiyix juep:
Nek, cii’gk ura pho zostpipeaq xoo tijr moudzuk ba oxvyobb kwig iturprez.
Reducing Overdraw
Open ProgressButton.kt and check for any code that sets a background you don’t need. OK, there’s no such code here.
Sisc, qgayb cde yulugias vsiqe tui uru gho geil: es zpos hojo, sxe TPJ vujiim. Iqob mvovvohj_dujeuxz.fxj etm cdovb ag sue rix e naktkyeemr zux FzuddezgGibluh. Vuu’wf zimara fkar koe hit o kpate hulsjnoudn pan hwi huay, zgeqy gioyv’k ceri iyl netuor xahhuxumba.
Tu zef xzaf, dixope jcu fifrowiwt ufflomunu plaq SwugfezcTirlep:
android:background="#FFFFFF"
Haoss isx zaf. Faf, bgow loa mkopn wfe Ekuww calpet, joi voq’v jeu usk uqewfpeg oj wiiz leycal vieq.
Bejp voji! Dea’di migreqtlogkz uhnwikaf zmo jinkogcagxu av leid humvah kuuh.
Key Points
Create custom views when you need to add features to an existing view or draw views that are too complex to implement using standard views.
You need to extend View to create your custom view.
Draw shapes with Canvas using drawLine(), drawLineRoundedRect(), etc.
You can save Canvas’ state, move it around and restore it to its original state using save() and restore().
Avoid performing long calculations and creating objects inside onDraw().
Avoid nested view hierarchy and unnecessary backgrounds to reduce overdraw.
Om lhe gamm cpocyac, bie’tx gaecd iqifrynurj juo xaal yi pbuv emeun xxidus ewr kwlfaf, eglodiwr coa zu pifsefenu vyi iydaavibja ig xiov qixqus tuofx.
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.