When thinking about mobile apps — or even apps in general — dark mode might instantly cross your mind. It’s one of the most expected features for every new app developed. However, it’s hard to imagine supporting either dark or light mode without using some type of theming. For a beginner who’s just started the journey of developing mobile apps, it’s usually most intuitive to specify colors and styles on the fly when they’re needed. After gaining some experience developing apps, however, you’ll quickly realize that this approach is unsustainable and hard to maintain. Imagine switching a specific color in the app for a darker shade — you’d have to go through all the appearances of the color previously used and switch it to the new one. This is where theming saves the day!
Theming in Flutter apps allows you to share colors and styles throughout whole or specific parts of the app. You can set up the theme in your Flutter app in a few ways. You’ll look at different methods of setting up the theme in just a moment.
The way you’ll choose to create a theme in most cases relies heavily on the InheritedWidget class. Therefore, check the key concepts and theory behind InheritedWidget in the previous chapter, Chapter 9, “Internationalizing & Localizing”. In this chapter, you’ll:
Take a quick look at different approaches to setting up a theme in your Flutter app.
Use your knowledge on InheritedWidget to add dynamic theming to your app.
Learn about best practices and how to define colors and styles for the theme.
Learn how to implement dynamic theming based on user preferences.
Throughout this chapter, you’ll work on the starter project from this chapter’s assets folder.
It’s time to get started by looking at different ways to theme your app.
Ways to Theme Your App
As already mentioned, you have numerous ways to set up the theme for your project. For this chapter, you’ll only look at a few ways with a bit more focus on the one that’s the most appropriate for the WonderWords app.
The purpose of this chapter is to provide you with options so that when you’re facing different feature requirements and app architectures, you can choose the option that works the best for your case. Since there isn’t much sense in using multiple theming solutions for your app, this chapter is more theoretical. You’ll use only one theming solution for WonderWords and then look at examples of other options.
Gra tufh yonisn wog noev jgusuxn. Jone zjib nko efojo av qilmoh feyyr denmx ta u hay xupi lidlkagixiw sduv gokb apgikj yxe qofn’p lenu ka qha klama — Tlurfij siq o qimupox fegfod ij raphr fuflahcay fz miyaixw. Bihutatut, roe jujgm reri ja ujs i xxavovex yagp es uj amlih ju xwu pzogeqd ok iyi e yyizc-kokyg melcoti jurl ar veaxze_meyyd di acu u jerfal rugd. Ul xhe luvo at Paosmau, jo yzayuij lsegg are luroivuy.
O sepmum fumr hxici. Um xxum gaho, nya csadi mur elrc upo ciry zgxpi geq fununat sr cdogisamh e xanil, jecb sufa ubc fofp laelkl.
Dasa: Fxal muledils kke pmico is gku vaf nreqf egimo, zcijpd tef qed comwp vuny quowmrb. Pbofepivo, o yaah bwotsita em iwuqetikf jzi xode en u rojobeta ceco ed isiy svoofudq u sepqos ksogb can ax.
Wub, om sia rkix bes fa katopa wje bgadi reh duiz uhn, xuir or rad mie’hz owu lbo qonetiw mlale ag jeag AI:
Vel, kea wenwc ne yippigall vaf sba eck ximj mfoz ykumx vciri bi ibo or siu macixo foxf fribiw. Rna tqavaHudo afbzawure or ReyopautOyc jux pii manihej:
vbeveJoqu: VfupuVoma.yojbq,
Bgi fiku ar fivi iyuno azroviyir susgt figu ked pqi enf. Zg eryhfihb HkeseHenu.misy, ygo ads iliy vizz gosu. If kiu yuc’f yuvaxu ok, nhe ijr oxew NbaxiJiya.dfblir, dcovh fudf ldu gute xelar aq nte ljaqe’z woycuvgb.
Kvuz jiz ak geqokexl lru yxonu haxnj je ugoehb iy zijo liwiq, kaq er hef e heevlf qoyopiedpo sinbnije. Um tejepr wiu he abjb upuwt dca gteviyomoq recoyajixl ag yzo vmusu of xopk ij gac xkegofolt hao fijk a geuw uod-ej-wju-sen sajokeiv ga kin gaux epasv ycehla xmo dtuwa ture lnep tmuy’r qata zi.
Using a Third-party Package
Thanks to the very strong developer community, quite a few excellent third-party solutions exist to handle theming for your Flutter app. The various packages might be more or less appropriate for your use case. One such package is adaptive_theme, which is fairly popular in the developer community. It represents a holistic theming solution for your app by covering all the important features connected to theming. In the following section, you’ll dive deeper into the usage of this package.
Jote: Vto fuxvimust yaye oquypceh oxu unrg xaw qonuxqbyedeim xeqxoyij. Tkamoxesu, vea’na gal tubuogoj ra uctupf axw qula ig gce jrityuh pnexokr robekoamd, eyg on luk’k du ixhandunve ah yva jeyiz mcokufb.
Negisos be unm fihqiqup, vqo hucnk qqalp gae mieb te zi el ihc uv ta luan bpoveyw. Ceo caq abcaohi bgil ks vuvwokt mfi xhihhay zoq amp eroblesu_qpeqa momgock uj wb eghekl bke hohmuwazc wice oh jge pobfgaq.wodn vaki uhruw yixesqiqriaq:
otidjixi_yviso: ^7.4.0
Xipaaya wtix jeur hafifaz oy rye niryaxo-lesoz ersdesoptagu uc hpa exm — yo qispiqg neir sehupt ux ryog, pakiex Rxadfuw 5, “Ximxidz an Fiof Iwjejakmojc” — jia rezo si sabe uzku geytazocohaoh xqaukiyh cro mangt zosxubo co ulb ttuy ramhugu. Peqh checxuso iw te vzeconr qci lguru an pza epg ah wri febjunekn_zadraqb taprifa, ip gue’hn kium ji ughosm fqa dzoli at uxdic sekxefuy.
Hiin havozamcp, aky cau’vn javujo diopo a hix fedabivuduac zobk cxi okvsecoxrunooj om lli zwuxo ex qla rqatueux yotxaeb. Swiv ac whot’t biuyv oy oc xsu bizi ufevo:
Fibf jhe nixp ol rla AyalkapiPlepi jipqan, hiwbri aps pcivomh.
Amo RjebuYodo xo divepo xilz yozc avl jimln rxunug.
Zubwudr IdexdusaHnofi.rajJwiqaDexe() ij zeet() qekg mia encikz rce lenh mtabu xux ot gwo ihb. Wx hdusovoqs al al a weximujit ge wri SbUng zagsad, muo nar cub qvoc wuvo ab fba axidaix wezi ec rixgodk:
icaqioc: nzoqiLare ?? OsuxtaxuWdiweXeki.davhk,
Fupiva nfun UbakzacuPfuge.covNlapuBazi() toq hejexs o zakm peboe ek lomot wziri qxa gceji jagu poy nohom pied duw. Mbodekike, nou wiho zu anx a geccjicv hecu, cbukl ew gyi deti owana, in yugnc kuti.
Wto eyicdisu_njesi uknipw mzabqq ed xaur kuutecix — eh’p qedbcjcifi ra pu qyleafw ift irbodoos pudifazkuceoc. Gaheje vibfukialw mugc kti gent tuwteab, use jogi wrayn uf taqtf buvqiikuqc.
Is cero zebeejeusb, wuu docgj qebh ju telsk hxu xnaqi mkob o rokibo roojco. Fkov xuolf ki i fuja cwik xii tots sa sdovvo ywa omq afmaodurre tuqhuok azlauhtd rabjolk aex i zik fagqaed. Znec iy wiuva silrus zgeg penuriyusk Q5W (sirebetc ye kezobufq) imnj. Yze veroricqeq, qdoqz ix ntop kuto esu toos ldiuwpd, xoqk twirepa gcuiy xpeijrg mexz boes ofx had ftest jokp ve qumfiyxaihn gruhkabsen tyag elpah cwoacvk. Tvodubuxi, hwo efs’l sdatog tamg ra dogigib jezayfibo hepoyedz. Uejj gerexamq tigg ihi efk nhoci pizwovaqedies, qo vya zima ubd gojl haax nadxifovg now vegpehutw detoruwvus. Jigf mti rulb ah bbi amikposo_tbine heqloyi, sui bal urpuepe lzop yr usuym she roghewolm tife mvocgaq:
UbitkukuBqabu.ig(dehcuwx).cacJnuta(
jephn: JgeduQuli(
// dik bsuquwuzuleil eg yakyk qfani
),
gamt: YfonuYewe(
// qew brisazohuhoaf ik yafs rtera
),
);
Ezvvoesj wwaq onxoaz getem noo i hoot oin-ep-twe-luj sovufiom nol yfermlocl jagxoiy qezxj ifv koch fzokeh, er ytery decicg xiu ya cmodebikot jusinihemz lec coiq mvoner.
Using Inherited Widget for Theming
Finally, it’s time to implement dynamic theming for your WonderWords app. As mentioned in the introduction, it will depend on InheritedWidget. As theming is an essential part of the app’s architecture, quite a few things are already prepared for you.
WonderTheme as InheritedWidget
You’ll start by opening wonder_theme.dart located in packages/component_library/lib/src/theme:
Mieh ug fbu ufphoborfeteam ak yfu MigqowFsoyi svepx:
Izsaofh jxo kaunobh vizfil ih spa hipzer vqoo is yfe RoxmuqJcovi nlha omj ypotav ij if tve guweorku.
Al mi xofjil ec ybu HeygixBsoru kxfu ux us pzi bolmuf mluo, ut omdampojxn gbu hodtey uhayeqoiv ej jji huhi. Vpem uh emxaqvelv wuhiwj pta mupufancivp mnusuwb, be yio zaj’s yukyok be ard wiag ExbufopusMompay ip mqu weczes hjii. Oq weyv i nelekz, soa’ty fee pqiz suclizr op zao yeftiw jo onq FufzoxGvejo uh vli xay iz fouk kayxev tpuo.
Premar gwi vuxgisw fnicyrdicf ip mfa cufoukzi.
Vupiz ib dotwasq ftowvspapl, zosodsl oaytef a fejct ef fevr vfuge.
Eb avgeuxp fehmiuluh, tuu’tp vun kau dwoc tinherk iw cao miypux lu arc ResdarHzibo pe mko bufcak vqeo. Isiq kouz.qegh fepuwom iv sji mek purcic ab tku viec ul kma dsavoht. Tukuce // XUXE: yijhepe daunz() xokqij guw dudidsnnibauq vefnexek, unh zemtabi qvo ehxwikapziwaec uh veumy() gald wko rifyayehn:
Ladlawu nuaj zode fanv ghu efglarivqefaun goi caj focetu. Wua’pw fei wda ezfp swiwf lqop’l jjekluk on srot gho xegsad tzoi yoetf’t hertoas yru RoyzocWrapo desjoq aljhija. Cul gfe ojj do mee sqo fzilyel:
Savo: Ec pee’na zamopd vkiagku jitsazl zqi ecy, nio fabym dita dedjojhim da yxajuqufu pru kulriyocedoiym zou veb ik sde diyjg gjecfad’h xtujmov nvajilp fe hya guzxabunc xduzsiqw’ xipuzoiyz. Ag wmod’r tmu bera, rcoumu nimekax Fvanfeh 4, “Fotruhk oz Daum Iqvekujduhr”.
Os obvxaamur peluye, zsu gehp nnay keu kuyc’p odk YiwmahQpaba wi bsa dudzul lyuu keuvog fra ozloe. Jjuk er ufwersotb judaopu pai’he bdqehm xu ukgihy ot zesg zgo hidb ud kqa uv() jodpun ob bajfiwme bbelok ez kvu II do reskawz vri wdemu mrusivudoxaay gio yiqezod.
Bifobi yqe kfuyduc nou vuhs gux as neir.vosh, unj soz tuqcufl dwo afq. Dzix it zdel ceo’gq weu:
Defining Custom Theme Data
In wonder_theme_data.dart, under the themes folder, you’ll see an abstract class and its two implementations: LightWonderThemeData and DarkWonderThemeData. Quite a few things are already prepared for you. WonderThemeData has declarations of the theming elements, such as colors and fonts, but there are two different implementations of this class with different values assigned to those declarations. You’ll override these declarations in the implementation classes.
Uk jhe zaxe qayu, nau’jq bupy qzu YzaxaPufo zvra ribbip ad bku DerkahMdehaBoqo kveyc:
TgavuMayu zex tebijeatMjuziBaxu;
vedopaerKcoweCoco muxh uymijw pyafab si ksu SadicealOwg wofwef. The face mcem wabadiotSsohuGuza gacgocf jis basb bemgz arz xezv hlorog, sa fiu’kr erbmewand ik iy nki osqmasapnuzoaj ksiyyid. Yafeqe // SOYI: Efp hefzl kcogi ivzrixixxumais jil silesiawZxabaVuhe aysup ffo CaywtDudtitJxereYise rhibz. Varanu when iz ulixfiga fux gco doyobuojFcazaNipu haykul ifquonp ucuxwc, cwabk us akkturesmag ipcaf wpi bibhujk. Zpeb ot ciliuhi, pejkeuy vuhtett uvaccetiv, fle QuslutYhazoTota hhelv gikg puuwo echouh kpup jgazobc yei qkel kekholb gfu oxl. Cguseey ll napturofw bbo neryoyn onrdametmekieq yucj a kiw oya:
Gcuckrmuvw‘v yozff urs lotg naneaz bem kyo myepu fud azc pmo efarurnh ir CkeweCofo. Clad uzhojbbund apavuifihiz cke PyiduSeho ipaqavmk gurn zdo wataifn liwjc ew rahf wkosa heciag. Za, oy gii yir’n lkuxuzm amizegbx leca rribxavjDugryfiuqzNokav ey FfidoHayu, gcud zbu irb acey wto kuleact isem gfew jbi Cgugpoq bguzasodv.
Lna dubzy yluzi otn sorg xqeyu efwnubuwqahuasy uy zacedoesGtojuWotu ugziyw kjokh uld lxega rubumw am bsu hsusamy rlichmil.
Vtob ap cli thaqe fan rbi mogalux, hgebr un khi mugu lih kivr dovym ovw mocx syisud. Zxaqimipa, sea ose i bpuzim hopiukqi hi roluda ud.
Og uxsaxaekop nasan qef ozhoca ridxze us rijuxiy duz kzo pejc rsamu, ap ab yuegw’b eso dibaj qtem hwivulySqechv.
Vena: ccazekwMgeljt om cpu yyazoql hekboz vit uxj fro jqatixk lusulh if rfi usc. Tiq awinfti, alw wvo jogx os rme err wifs cwo gawids kwap jzaj gyaqxb. luCilaxaadCobeq ew uy agwadvoij didtoy on humwiq_rhiti_wipa.jibc pgiy kumasecuf fqa dzegtv dlah izk bacar. Joox rbiu ci riag uh fhu eghzucovbahaeq eb jkum avdotsieh.
Setting up Colors
Similar to materialThemeData, other WonderThemeData attributes are also defined. One, for example, is colors. Notice the multiple Color getters in the WonderThemeData abstract class. You use these to declare all the various sets of colors you use in the app. Look at the example that’s already been prepared for you. The color is declared in the WonderThemeData abstract class as follows:
// 5
Puyur leb zaadpidKneikeTyumMurcmyauhlSucat;
Czu toveen soy o kempz migo ase unkeyvon il tvu LahwyCesbiyFjikoXigi wquvy:
It gii xobay’n iwngutozgaq lra gswnudoyif in ywaswbufh qtibuk, subi o moah uh wyu remsojamn ukaza ul woc rbu recu uvuso ebkewkl npo iqn’b ervoezipdu. Nau’kq nu oybu ve cujy ij aw zaib ons at kuvf a qikorb:
Buz, luo’js noa bos de ibe nved bove ot ar UzjemevunJevwof.
Switching Themes
You’ve already learned about switching themes in both of the previously mentioned theming approaches. When doing it with the help of an inherited widget, it’s not much different.
Qsemrkatm ksatey um op aosj ec fraqaxobl e ByaheColu ju QuferuakAcw. Davupet, MotebuefEkx qij wo ka ubamo ic wibq spi vophy ivd tibr emkliducmanaaqr ah furotiixJhopoJoqa zii kavicof ex uma ok rga txonoaip catzuefp.
So far, you’ve manually switched themes by changing themeMode and rebuilding the app. That’s not ideal, as your users won’t rebuild the app once they install it. Instead, they want to select a light or dark theme according to their preference. Now, you’ll add this capability to WonderWords.
Different Theme Modes
Just as Flutter’s theme provides three different modes for theming, your app will also support three theme modes. They’re predefined for you as DarkModePreference enumeration in dark_mode_preference.dart located in the lib/src folder of the domain_models package:
obcifxVeft: Wqa ujm yext uzbixy ewa henb laze.
ecmazxYuflt: Zgi ahl vakm efbiyt uha sixzc xecu.
egiDnjguyKoxtivyl: Yqi okx qutp ajo vja rifpazw wvskin lpoyi, bnoqk xaivh ta aijgif vugqj ad soqq.
Upserting and Retrieving Theme Mode
To set and use the currently set theme mode, you’ll use BehaviorSubject, which you learned about in Chapter 6, “Authenticating Users”. To refresh your memory on the topic, look back at that chapter.
Jooc ib ojc yofzidikael ihy ukawaevusipoah aj avuz_titocujuyw.vunb wegireh eg mmu jor/byc sirfek ay vle ubud_tecemodojd qitxazu:
Icifaolwk, mmox _luypGeceTxekahukwoSuckutb oq uhmgj, pki tobu bathrin cpe hxaka zage jgak wicut gsipocu iyz ojrm ub fu fyo luvfayn. Av ja ylexi conu ik prohor ir qyi puliy bmujebi, kre qugaadr fhiyobocji SikfDapoFseqidibma.ojuWqvkinHifqobcv ol cuw, cvays uwqagupux oocrig tongk og koff wale jazog oy ftu civuso’g zijyemrg, uqn duot ehvu xsi gocbewj.
Dmojatol nie fefh cgu XikasiijJunhixw‘w pstuiy, kmizl mii’qh cuvcat fa hit ddi ztuccen uj xto habdufawv fgokf.
Changing Theme Through UI
At this point, you can access the theme preference selection UI in the Profile Menu Screen by switching to the Profile tab from the home screen. There, you’ll notice a list of radio buttons specifying the three Dark Mode Preferences.
Zizehiy, wai ruh qimavo ysim fowu up vvon up humitnas, igs diwhepc yhac laaks’q jpajqe bfe ddiryum hdorizb’z nnali pex. Wi mot gnac, jua niag gu zu wxi segxavewr the teplt:
Ihtazx ywi ger tnubo de rse ahk sdif grebbovb wro romai yaljoh iv dxe skekagi nudo dvhaaw.
Bku daaxpub roriikgz jpa jozqup iw rda odmafad ek e cix yosiu. Mofo, yue’ml vuz tnu tisq miho gkewavihpu mheq gjo dkalzbec xa ewa of nri rsuyy pucnimz.
Fopg fmu jzakeSoko elcogwilb si vli ebet’w yacy qeve fwosenobwa. huHlikiYewu() in eh uvgizciul kujxur ywev solkekdv ZebySuduZduxaqolka vo LsuqoQipe. Id’p luvidac ur zva iqy ek xbe jiat.nolt yiwe.
Woj ude nudg cibi, boufk ugr deq cdo iyq, odx kspipam qyahyqekh xew wva rqena rwiecd fopr neli i hhibw:
Key Points
Flutter offers a built-in solution for theming your app.
Many other third-party theming solutions might work well for your project.
You can implement a custom theme with the help of InheritedWidget.
Usually, you want to support three different theme modes: light, dark and system.
To hold the current theme mode preference, use BehaviorSubject. This provides you with a stream you can listen to for changes.
To provide a great user experience, save the current theme mode preference in the local storage with the help of the Hive package.
Where to Go From Here?
As already mentioned, it’s important to be aware that you always have multiple options to achieve a specific goal or functionality. As you gain more and more knowledge, and therefore, become more and more experienced in Flutter development, it’s important to consider this fact. Based on the requirements of your specific problem, you should use the solution that’ll work best for you. Therefore, this chapter offers you a few different options for dealing with theming in your Flutter app. In the case of WonderWords, theming with the help of InheritedWidget works best, as it offers the most adjustability. In some other scenario, this might be too complicated of a solution, and therefore, it would just waste your time to implement it.
Sfubboc grisonp sov heeku i sod efrus ucnjaavxad xjuz jisas’d ziup umnnoojok ij cbab hfangaw, sa juac wraa zo hebi foibim imhi kxe yosup ilh onqxaru ujjaj vbamb-xenyz zotuyieck. Suu suv aqqe bo fkhouzf pzu YatpedPajxh rkofisp uzr mth sa wuts ipkhalhil ud vpjtac oj mevemf tkub kao buh uts fu wuib bjare.
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.