/* Ċ Ġ* ĠCopyright Ġ 2 0 2 1 ĠThe ĠAndroid ĠOpen ĠSource ĠProject Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttps :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . example . android dev challenge Ċ Ċ import Ġandroid . os . Bundle Ċ import Ġandroidx . activity . compose . setContent Ċ import Ġandroidx . activity . view Models Ċ import Ġandroidx . appcompat . app . AppCompatActivity Ċ import Ġandroidx . compose . animation . animate Color As State Ċ import Ġandroidx . compose . animation . core . t ween Ċ import Ġandroidx . compose . foundation . background Ċ import Ġandroidx . compose . foundation . layout . Arrange ment Ċ import Ġandroidx . compose . foundation . layout . Box Ċ import Ġandroidx . compose . foundation . layout . Column Ċ import Ġandroidx . compose . foundation . layout . Row Ċ import Ġandroidx . compose . foundation . layout . fill Max Width Ċ import Ġandroidx . compose . foundation . layout . padding Ċ import Ġandroidx . compose . foundation . layout . required Width Ċ import Ġandroidx . compose . material . Floating ActionButton Ċ import Ġandroidx . compose . material . Icon Ċ import Ġandroidx . compose . material . Material Theme Ċ import Ġandroidx . compose . material . Outlined Button Ċ import Ġandroidx . compose . material . Outlined TextField Ċ import Ġandroidx . compose . material . Sca ffold Ċ import Ġandroidx . compose . material . Surface Ċ import Ġandroidx . compose . material . Text Ċ import Ġandroidx . compose . material . Top AppBar Ċ import Ġandroidx . compose . material . icons . Icons Ċ import Ġandroidx . compose . material . icons . filled . Arrow Down ward Ċ import Ġandroidx . compose . material . icons . filled . Arrow Up ward Ċ import Ġandroidx . compose . material . icons . filled . Pause Ċ import Ġandroidx . compose . material . icons . filled . Play Arrow Ċ import Ġandroidx . compose . runtime . Composable Ċ import Ġandroidx . compose . runtime . getValue Ċ import Ġandroidx . compose . runtime . li ved ata . observe As State Ċ import Ġandroidx . compose . ui . Alignment Ċ import Ġandroidx . compose . ui . Modifier Ċ import Ġandroidx . compose . ui . res . string Resource Ċ import Ġandroidx . compose . ui . tool ing . preview . Preview Ċ import Ġandroidx . compose . ui . unit . dp Ċ import Ġandroidx . core . text . is Digits Only Ċ import Ġcom . example . android dev challenge . ui . theme . Count Down Theme Ċ import Ġcom . example . android dev challenge . util . Notification Util Ċ Ċ class ĠMainActivity Ġ: ĠAppCompatActivity () Ġ{ ĊĠĠĠ Ġprivate Ġval Ġmain ViewModel Ġby Ġview Models < Main ViewModel >() ĊĊĠĠĠ Ġoverride Ġfun ĠonCreate ( savedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . onCreate ( savedInstanceState ) ĊĊĠĠĠĠĠĠĠ Ġset Content Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCount Down Theme Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstarted : ĠBoolean Ġby Ġmain ViewModel . started . observe As State ( false ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbackground Ġby Ġanimate Color As State ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget Value Ġ= Ġif Ġ( started ) ĠMaterial Theme . colors . secondary ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse ĠMaterial Theme . colors . secondary Variant , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġanimation Spec Ġ= Ġt ween ( duration Millis Ġ= Ġ 5 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠScaffold ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier . background ( background ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtop Bar Ġ= Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTop AppBar ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtitle Ġ= Ġ{ ĠText ( text Ġ= Ġ" Count ĠDown ") Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelevation Ġ= Ġ 1 6 . dp , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfloating ActionButton Ġ= Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStart End Floating ActionButton ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstarted Ġ= Ġstarted ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmain ViewModel . toggle Start Pause Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠNotification Util . show Timer Expired ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠSurface () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMain ( main ViewModel Ġ= Ġmain ViewModel ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Composable Ċ fun ĠNumeric UpDown ( ĊĠĠĠ Ġvalue : ĠLong Ġ= Ġ 0 , ĊĠĠĠ Ġrange : ĠLong Range Ġ= ĠLong Range ( 0 , Ġ 6 0 ), ĊĠĠĠ Ġon Value Change : Ġ( Long ) Ġ-> ĠUnit Ċ ) Ġ{ ĊĊĠĠĠ Ġval Ġupdate Value Ġ= Ġ{ ĠnewValue : ĠLong Ġ-> ĊĠĠĠĠĠĠĠ Ġon Value Change ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrange . contains ( newValue ) Ġ-> ĠnewValue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠnewValue Ġ< Ġrange . first Ġ-> Ġrange . first ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠnewValue Ġ> Ġrange . last Ġ-> Ġrange . last ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġupdate Value With Text Ġ= Ġ{ Ġstr : ĠString Ġ-> ĊĠĠĠĠĠĠĠ Ġif Ġ( str . isNotEmpty () Ġ&& Ġstr . is Digits Only ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Value ( str . to Long ()) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġupdate Value ( 0 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ ĠColumn ( ĊĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. padding ( start Ġ= Ġ 8 . dp , Ġend Ġ= Ġ 8 . dp ), ĊĠĠĠĠĠĠĠ Ġhorizontal Alignment Ġ= ĠAlignment . Center H orizontally ĊĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ ĠOut lined Button ( onClick Ġ= Ġ{ Ġupdate Value ( value Ġ+ Ġ 1 ) Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠIcon ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimage Vector Ġ= ĠIcons . Default . Arrow Up ward , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Description Ġ= Ġstring Resource ( R . string . up ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠBox ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. padding ( bottom Ġ= Ġ 4 . dp ) ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOut lined TextField ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Ġ= Ġvalue . toString (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġon Value Change Ġ= Ġ{ Ġupdate Value With Text ( it ) Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsingle Line Ġ= Ġtrue , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. required Width ( 5 2 . dp ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ ĠOut lined Button ( onClick Ġ= Ġ{ Ġupdate Value ( value Ġ- Ġ 1 ) Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠIcon ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimage Vector Ġ= ĠIcons . Default . Arrow Down ward , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Description Ġ= Ġstring Resource ( R . string . down ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Composable Ċ fun ĠTimeUnit Text ( ĊĠĠĠ Ġtext : ĠString Ċ ) Ġ{ ĊĠĠĠ ĠText ( ĊĠĠĠĠĠĠĠ Ġtext Ġ= Ġtext , ĊĠĠĠ Ġ) Ċ } Ċ Ċ // ĠStart Ġbuilding Ġyour Ġapp Ġhere ! Ċ @ Composable Ċ fun ĠMain ( main ViewModel : ĠMain ViewModel ) Ġ{ ĊĠĠĠ ĠColumn () Ġ{ ĊĠĠĠĠĠĠĠ ĠRow ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. fill Max Width () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. padding ( 8 . dp ), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġhorizontal Arrange ment Ġ= ĠArrange ment . Center , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvertical Alignment Ġ= ĠAlignment . Center Vert ically ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhours Ġby Ġmain ViewModel . hours . observe As State ( 0 L ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNumeric UpDown ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Ġ= Ġhours , Ġrange Ġ= Ġ 0 .. 2 3 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ Ġmain ViewModel . on Hours Change ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTimeUnit Text ( text Ġ= Ġ" h ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġminutes Ġby Ġmain ViewModel . minutes . observe As State ( 0 L ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNumeric UpDown ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Ġ= Ġminutes , Ġrange Ġ= Ġ 0 .. 6 0 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ Ġmain ViewModel . on Minutes Change ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTimeUnit Text ( text Ġ= Ġ" m ") ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġseconds Ġby Ġmain ViewModel . seconds . observe As State ( 0 L ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠNumeric UpDown ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Ġ= Ġseconds , Ġrange Ġ= Ġ 0 .. 6 0 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ Ġmain ViewModel . on Seconds Change ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTimeUnit Text ( text Ġ= Ġ" s ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Composable Ċ fun ĠStart End Floating ActionButton ( ĊĠĠĠ Ġstarted : ĠBoolean , ĊĠĠĠ ĠonClick : Ġ() Ġ-> ĠUnit Ċ ) Ġ{ ĊĠĠĠ ĠFloating ActionButton ( onClick Ġ= ĠonClick ) Ġ{ ĊĠĠĠĠĠĠĠ ĠRow ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier . padding ( horizontal Ġ= Ġ 1 6 . dp ) ĊĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠIcon ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimage Vector Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstarted Ġ-> ĠIcons . Default . Pause ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠIcons . Default . Play Arrow ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontent Description Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠText ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmodifier Ġ= ĠModifier ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. padding ( start Ġ= Ġ 8 . dp , Ġtop Ġ= Ġ 3 . dp ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtext Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstarted Ġ-> Ġstring Resource ( id Ġ= ĠR . string . end ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġstring Resource ( id Ġ= ĠR . string . start ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Preview (" Light ĠTheme ", Ġwidth Dp Ġ= Ġ 3 6 0 , Ġheight Dp Ġ= Ġ 6 4 0 ) Ċ @ Composable Ċ fun ĠLight Preview () Ġ{ ĊĠĠĠ Ġval Ġmain ViewModel Ġ= ĠMain ViewModel () ĊĠĠĠ ĠCount Down Theme Ġ{ ĊĠĠĠĠĠĠĠ ĠMain ( main ViewModel ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Preview (" Dark ĠTheme ", Ġwidth Dp Ġ= Ġ 3 6 0 , Ġheight Dp Ġ= Ġ 6 4 0 ) Ċ @ Composable Ċ fun ĠDark Preview () Ġ{ ĊĠĠĠ Ġval Ġmain ViewModel Ġ= ĠMain ViewModel () ĊĠĠĠ ĠCount Down Theme ( dark Theme Ġ= Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠ ĠMain ( main ViewModel ) ĊĠĠĠ Ġ} Ċ } Ċ