CINXE.COM

<!doctype html><html lang="en"><head><title data-rh="true">Custom modifiers in Jetpack Compose | by Siddharth Gupta | Nov, 2024 | ProAndroidDev</title><meta data-rh="true" charset="utf-8"/><meta data-rh="true" name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1,maximum-scale=1"/><meta data-rh="true" name="theme-color" content="#000000"/><meta data-rh="true" name="twitter:app:name:iphone" content="Medium"/><meta data-rh="true" name="twitter:app:id:iphone" content="828256236"/><meta data-rh="true" property="al:ios:app_name" content="Medium"/><meta data-rh="true" property="al:ios:app_store_id" content="828256236"/><meta data-rh="true" property="al:android:package" content="com.medium.reader"/><meta data-rh="true" property="fb:app_id" content="542599432471018"/><meta data-rh="true" property="og:site_name" content="Medium"/><meta data-rh="true" property="og:type" content="article"/><meta data-rh="true" property="article:published_time" content="2024-11-22T04:11:37.520Z"/><meta data-rh="true" name="title" content="Custom modifiers in Jetpack Compose | by Siddharth Gupta | Nov, 2024 | ProAndroidDev"/><meta data-rh="true" property="og:title" content="Custom modifiers in Jetpack Compose"/><meta data-rh="true" property="al:android:url" content="medium://p/a950e6f9eb72"/><meta data-rh="true" property="al:ios:url" content="medium://p/a950e6f9eb72"/><meta data-rh="true" property="al:android:app_name" content="Medium"/><meta data-rh="true" name="description" content="Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the appearance, behaviour, and layout of composable functions without…"/><meta data-rh="true" property="og:description" content="Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the…"/><meta data-rh="true" property="og:url" content="https://proandroiddev.com/custom-modifiers-in-jetpack-compose-a950e6f9eb72"/><meta data-rh="true" property="al:web:url" content="https://proandroiddev.com/custom-modifiers-in-jetpack-compose-a950e6f9eb72"/><meta data-rh="true" property="og:image" content="https://miro.medium.com/v2/resize:fit:1024/1*Oe-DGannPg34NnFtp02TjA.png"/><meta data-rh="true" property="article:author" content="https://medium.com/@siddh.gupta99"/><meta data-rh="true" name="author" content="Siddharth Gupta"/><meta data-rh="true" name="robots" content="index,noarchive,follow,max-image-preview:large"/><meta data-rh="true" name="referrer" content="unsafe-url"/><meta data-rh="true" property="twitter:title" content="Custom modifiers in Jetpack Compose"/><meta data-rh="true" name="twitter:site" content="@proandroiddev"/><meta data-rh="true" name="twitter:app:url:iphone" content="medium://p/a950e6f9eb72"/><meta data-rh="true" property="twitter:description" content="Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the…"/><meta data-rh="true" name="twitter:image:src" content="https://miro.medium.com/v2/resize:fit:1024/1*Oe-DGannPg34NnFtp02TjA.png"/><meta data-rh="true" name="twitter:card" content="summary_large_image"/><meta data-rh="true" name="twitter:label1" content="Reading time"/><meta data-rh="true" name="twitter:data1" content="5 min read"/><link data-rh="true" rel="icon" href="https://miro.medium.com/v2/resize:fill:256:256/1*A8VytPZQhvUf_MG6hm_Dlw.png"/><link data-rh="true" rel="search" type="application/opensearchdescription+xml" title="Medium" href="/osd.xml"/><link data-rh="true" rel="apple-touch-icon" sizes="152x152" href="https://miro.medium.com/v2/resize:fill:304:304/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="120x120" href="https://miro.medium.com/v2/resize:fill:240:240/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="76x76" href="https://miro.medium.com/v2/resize:fill:152:152/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="apple-touch-icon" sizes="60x60" href="https://miro.medium.com/v2/resize:fill:120:120/10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156"/><link data-rh="true" rel="mask-icon" href="https://miro.medium.com/v2/resize:fill:1000:1000/7*GAOKVe--MXbEJmV9230oOQ.png" color="#171717"/><link data-rh="true" id="glyph_preload_link" rel="preload" as="style" type="text/css" href="https://glyph.medium.com/css/unbound.css"/><link data-rh="true" id="glyph_link" rel="stylesheet" type="text/css" href="https://glyph.medium.com/css/unbound.css"/><link data-rh="true" rel="author" href="https://medium.com/@siddh.gupta99"/><link data-rh="true" rel="canonical" href="https://proandroiddev.com/custom-modifiers-in-jetpack-compose-a950e6f9eb72"/><link data-rh="true" rel="alternate" href="android-app://com.medium.reader/https/medium.com/p/a950e6f9eb72"/><script data-rh="true" type="application/ld+json">{"@context":"http:\u002F\u002Fschema.org","@type":"NewsArticle","image":["https:\u002F\u002Fmiro.medium.com\u002Fv2\u002Fresize:fit:1200\u002F1*Oe-DGannPg34NnFtp02TjA.png"],"url":"https:\u002F\u002Fproandroiddev.com\u002Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72","dateCreated":"2024-11-22T04:11:37.520Z","datePublished":"2024-11-22T04:11:37.520Z","dateModified":"2024-11-23T02:54:19.568Z","headline":"Custom modifiers in Jetpack Compose - ProAndroidDev","name":"Custom modifiers in Jetpack Compose - ProAndroidDev","description":"Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the appearance, behaviour, and layout of composable functions without…","identifier":"a950e6f9eb72","author":{"@type":"Person","name":"Siddharth Gupta","url":"https:\u002F\u002Fproandroiddev.com\u002F@siddh.gupta99"},"creator":["Siddharth Gupta"],"publisher":{"@type":"Organization","name":"ProAndroidDev","url":"proandroiddev.com","logo":{"@type":"ImageObject","width":272,"height":60,"url":"https:\u002F\u002Fmiro.medium.com\u002Fv2\u002Fresize:fit:544\u002F7*V1_7XP4snlmqrc_0Njontw.png"}},"mainEntityOfPage":"https:\u002F\u002Fproandroiddev.com\u002Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72"}</script><style type="text/css" data-fela-rehydration="572" data-fela-type="STATIC">html{box-sizing:border-box;-webkit-text-size-adjust:100%}*, *:before, *:after{box-sizing:inherit}body{margin:0;padding:0;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:rgba(0,0,0,0.8);position:relative;min-height:100vh}h1, h2, h3, h4, h5, h6, dl, dd, ol, ul, menu, figure, blockquote, p, pre, form{margin:0}menu, ol, ul{padding:0;list-style:none;list-style-image:none}main{display:block}a{color:inherit;text-decoration:none}a, button, input{-webkit-tap-highlight-color:transparent}img, svg{vertical-align:middle}button{background:transparent;overflow:visible}button, input, optgroup, select, textarea{margin:0}:root{--reach-tabs:1;--reach-menu-button:1}#speechify-root{font-family:Sohne, sans-serif}div[data-popper-reference-hidden="true"]{visibility:hidden;pointer-events:none}.grecaptcha-badge{visibility:hidden} /*XCode style (c) Angel Garcia <angelgarcia.mail@gmail.com>*/.hljs {background: #fff;color: black; }/* Gray DOCTYPE selectors like WebKit */ .xml .hljs-meta {color: #c0c0c0; }.hljs-comment, .hljs-quote {color: #007400; }.hljs-tag, .hljs-attribute, .hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-name {color: #aa0d91; }.hljs-variable, .hljs-template-variable {color: #3F6E74; }.hljs-code, .hljs-string, .hljs-meta .hljs-string {color: #c41a16; }.hljs-regexp, .hljs-link {color: #0E0EFF; }.hljs-title, .hljs-symbol, .hljs-bullet, .hljs-number {color: #1c00cf; }.hljs-section, .hljs-meta {color: #643820; }.hljs-title.class_, .hljs-class .hljs-title, .hljs-type, .hljs-built_in, .hljs-params {color: #5c2699; }.hljs-attr {color: #836C28; }.hljs-subst {color: #000; }.hljs-formula {background-color: #eee;font-style: italic; }.hljs-addition {background-color: #baeeba; }.hljs-deletion {background-color: #ffc8bd; }.hljs-selector-id, .hljs-selector-class {color: #9b703f; }.hljs-doctag, .hljs-strong {font-weight: bold; }.hljs-emphasis {font-style: italic; } </style><style type="text/css" data-fela-rehydration="572" data-fela-type="KEYFRAME">@-webkit-keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}@-moz-keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}@keyframes k1{0%{opacity:0.8}50%{opacity:0.5}100%{opacity:0.8}}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE">.a{font-family:medium-content-sans-serif-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif}.b{font-weight:400}.c{background-color:rgba(255, 255, 255, 1)}.l{display:block}.m{position:sticky}.n{top:0}.o{z-index:500}.p{padding:0 24px}.q{align-items:center}.r{border-bottom:solid 1px #F2F2F2}.y{height:41px}.z{line-height:20px}.ab{display:flex}.ac{height:57px}.ae{flex:1 0 auto}.af{color:inherit}.ag{fill:inherit}.ah{font-size:inherit}.ai{border:inherit}.aj{font-family:inherit}.ak{letter-spacing:inherit}.al{font-weight:inherit}.am{padding:0}.an{margin:0}.ao{cursor:pointer}.ap:disabled{cursor:not-allowed}.aq:disabled{color:#6B6B6B}.ar:disabled{fill:#6B6B6B}.au{width:auto}.av path{fill:#242424}.aw{height:25px}.ax{margin-left:16px}.ay{border:none}.az{border-radius:20px}.ba{width:240px}.bb{background:#F9F9F9}.bc path{fill:#6B6B6B}.be{outline:none}.bf{font-family:sohne, "Helvetica Neue", Helvetica, Arial, sans-serif}.bg{font-size:14px}.bh{width:100%}.bi{padding:10px 20px 10px 0}.bj{background-color:transparent}.bk{color:#242424}.bl::placeholder{color:#6B6B6B}.bm{display:inline-block}.bn{margin-left:12px}.bo{margin-right:12px}.bp{border-radius:4px}.bq{margin-left:24px}.br{height:24px}.bx{background-color:#F9F9F9}.by{border-radius:50%}.bz{height:32px}.ca{width:32px}.cb{justify-content:center}.ch{max-width:680px}.ci{min-width:0}.cj{animation:k1 1.2s ease-in-out infinite}.ck{height:100vh}.cl{margin-bottom:16px}.cm{margin-top:48px}.cn{align-items:flex-start}.co{flex-direction:column}.cp{justify-content:space-between}.cq{margin-bottom:24px}.cw{width:80%}.cx{background-color:#F2F2F2}.dd{height:44px}.de{width:44px}.df{margin:auto 0}.dg{margin-bottom:4px}.dh{height:16px}.di{width:120px}.dj{width:80px}.dp{margin-bottom:8px}.dq{width:96%}.dr{width:98%}.ds{width:81%}.dt{margin-left:8px}.du{color:#6B6B6B}.dv{font-size:13px}.dw{height:100%}.ep{color:#FFFFFF}.eq{fill:#FFFFFF}.er{background:rgba(46, 152, 126, 1)}.es{border-color:rgba(46, 152, 126, 1)}.ew:disabled{cursor:inherit !important}.ex:disabled{opacity:0.3}.ey:disabled:hover{background:rgba(46, 152, 126, 1)}.ez:disabled:hover{border-color:rgba(46, 152, 126, 1)}.fa{border-radius:99em}.fb{border-width:1px}.fc{border-style:solid}.fd{box-sizing:border-box}.fe{text-decoration:none}.ff{text-align:center}.fi{margin-right:32px}.fj{position:relative}.fk{fill:#6B6B6B}.fn{background:transparent}.fo svg{margin-left:4px}.fp svg{fill:#6B6B6B}.fr{box-shadow:inset 0 0 0 1px rgba(0, 0, 0, 0.05)}.fs{position:absolute}.fz{margin:0 24px}.gd{background:rgba(255, 255, 255, 1)}.ge{border:1px solid #F2F2F2}.gf{box-shadow:0 1px 4px #F2F2F2}.gg{max-height:100vh}.gh{overflow-y:auto}.gi{left:0}.gj{top:calc(100vh + 100px)}.gk{bottom:calc(100vh + 100px)}.gl{width:10px}.gm{pointer-events:none}.gn{word-break:break-word}.go{word-wrap:break-word}.gp:after{display:block}.gq:after{content:""}.gr:after{clear:both}.gs{line-height:1.23}.gt{letter-spacing:0}.gu{font-style:normal}.gv{font-weight:700}.ia{align-items:baseline}.ib{width:48px}.ic{height:48px}.id{border:2px solid rgba(255, 255, 255, 1)}.ie{z-index:0}.if{box-shadow:none}.ig{border:1px solid rgba(0, 0, 0, 0.05)}.ih{margin-left:-12px}.ii{width:28px}.ij{height:28px}.ik{z-index:1}.il{width:24px}.im{margin-bottom:2px}.in{flex-wrap:nowrap}.io{font-size:16px}.ip{line-height:24px}.ir{margin:0 8px}.is{display:inline}.it{color:rgba(46, 152, 126, 1)}.iu{fill:rgba(46, 152, 126, 1)}.ix{flex:0 0 auto}.ja{flex-wrap:wrap}.jd{white-space:pre-wrap}.je{margin-right:4px}.jf{overflow:hidden}.jg{max-height:20px}.jh{text-overflow:ellipsis}.ji{display:-webkit-box}.jj{-webkit-line-clamp:1}.jk{-webkit-box-orient:vertical}.jl{word-break:break-all}.jn{padding-left:8px}.jo{padding-right:8px}.kp> *{flex-shrink:0}.kq{overflow-x:scroll}.kr::-webkit-scrollbar{display:none}.ks{scrollbar-width:none}.kt{-ms-overflow-style:none}.ku{width:74px}.kv{flex-direction:row}.kw{z-index:2}.kz{-webkit-user-select:none}.la{border:0}.lb{fill:rgba(117, 117, 117, 1)}.le{outline:0}.lf{user-select:none}.lg> svg{pointer-events:none}.lp{cursor:progress}.lq{opacity:1}.lr{padding:4px 0}.lu{margin-top:0px}.lv{width:16px}.lx{display:inline-flex}.md{max-width:100%}.me{padding:8px 2px}.mf svg{color:#6B6B6B}.mw{margin-left:auto}.mx{margin-right:auto}.my{max-width:1024px}.ne{clear:both}.ng{cursor:zoom-in}.nh{z-index:auto}.nj{height:auto}.nk{line-height:1.58}.nl{letter-spacing:-0.004em}.nm{font-family:source-serif-pro, Georgia, Cambria, "Times New Roman", Times, serif}.oh{margin-bottom:-0.46em}.oi{line-height:1.12}.oj{letter-spacing:-0.022em}.ok{font-weight:600}.pf{margin-bottom:-0.28em}.pl{list-style-type:disc}.pm{margin-left:30px}.pn{padding-left:0px}.pt{list-style-type:decimal}.pz{overflow-x:auto}.qa{font-family:source-code-pro, Menlo, Monaco, "Courier New", Courier, monospace}.qb{padding:32px}.qc{border:1px solid #E5E5E5}.qd{line-height:1.4}.qe{margin-top:-0.2em}.qf{margin-bottom:-0.2em}.qg{white-space:pre}.qh{min-width:fit-content}.qi{margin:auto}.qj{padding-bottom:100%}.qk{height:0}.ql{box-shadow:inset 3px 0 0 0 #242424}.qm{padding-left:23px}.qn{margin-left:-20px}.qo{font-style:italic}.qp{text-decoration:underline}.qq{padding:2px 4px}.qr{font-size:75%}.qs> strong{font-family:inherit}.qt{line-height:1.18}.rh{margin-bottom:-0.31em}.ri{max-width:1532px}.rj{margin-top:10px}.rk{max-width:728px}.rn{margin-bottom:26px}.ro{margin-top:6px}.rp{margin-top:8px}.rq{margin-right:8px}.rr{padding:8px 16px}.rs{border-radius:100px}.rt{transition:background 300ms ease}.rv{white-space:nowrap}.rw{border-top:none}.rx{margin-bottom:14px}.ry{height:52px}.rz{max-height:52px}.sa{box-sizing:content-box}.sb{position:static}.sd{max-width:155px}.sj{margin-right:20px}.sp{height:0px}.sq{margin-bottom:40px}.sr{margin-bottom:48px}.tf{border-radius:2px}.th{height:64px}.ti{width:64px}.tj{align-self:flex-end}.tk{color:rgba(255, 255, 255, 1)}.tl{fill:rgba(255, 255, 255, 1)}.tm{background:rgba(25, 25, 25, 1)}.tn{border-color:rgba(25, 25, 25, 1)}.tq:disabled{opacity:0.1}.tr:disabled:hover{background:rgba(25, 25, 25, 1)}.ts:disabled:hover{border-color:rgba(25, 25, 25, 1)}.tt{flex:1 1 auto}.tz{padding-right:4px}.ua{font-weight:500}.uh{margin-top:16px}.ui{margin-bottom:54px}.uo{gap:18px}.up{fill:rgba(61, 61, 61, 1)}.uw{border-bottom:solid 1px #E5E5E5}.ux{margin-top:72px}.uy{padding:24px 0}.uz{margin-bottom:0px}.va{margin-right:16px}.as:hover:not(:disabled){color:rgba(25, 25, 25, 1)}.at:hover:not(:disabled){fill:rgba(25, 25, 25, 1)}.et:hover{background:rgba(50, 130, 108, 1)}.eu:hover{border-color:rgba(50, 130, 108, 1)}.ev:hover{cursor:pointer}.fl:hover{color:#242424}.fm:hover{fill:#242424}.fq:hover svg{fill:#242424}.ft:hover{background-color:rgba(0, 0, 0, 0.1)}.iq:hover{text-decoration:underline}.iv:hover:not(:disabled){color:rgba(50, 130, 108, 1)}.iw:hover:not(:disabled){fill:rgba(50, 130, 108, 1)}.ld:hover{fill:rgba(8, 8, 8, 1)}.ls:hover{fill:#000000}.lt:hover p{color:#000000}.lw:hover{color:#000000}.mg:hover svg{color:#000000}.ru:hover{background-color:#F2F2F2}.tg:hover{background-color:none}.to:hover{background:#000000}.tp:hover{border-color:#242424}.uq:hover{fill:rgba(25, 25, 25, 1)}.bd:focus-within path{fill:#242424}.lc:focus{fill:rgba(8, 8, 8, 1)}.mh:focus svg{color:#000000}.ni:focus{transform:scale(1.01)}.lh:active{border-style:none}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (min-width: 1080px)">.d{display:none}.bw{width:64px}.cg{margin:0 64px}.cv{height:48px}.dc{margin-bottom:52px}.do{margin-bottom:48px}.ef{font-size:14px}.eg{line-height:20px}.em{font-size:13px}.eo{padding:5px 12px}.fh{display:flex}.fy{margin-bottom:68px}.gc{max-width:680px}.hq{font-size:42px}.hr{margin-top:1.19em}.hs{margin-bottom:32px}.ht{line-height:52px}.hu{letter-spacing:-0.011em}.hz{align-items:center}.kb{border-top:solid 1px #F2F2F2}.kc{border-bottom:solid 1px #F2F2F2}.kd{margin:32px 0 0}.ke{padding:3px 8px}.kn> *{margin-right:24px}.ko> :last-child{margin-right:0}.lo{margin-top:0px}.mc{margin:0}.nd{margin-top:40px}.od{font-size:20px}.oe{margin-top:2.14em}.of{line-height:32px}.og{letter-spacing:-0.003em}.pb{font-size:24px}.pc{margin-top:1.95em}.pd{line-height:30px}.pe{letter-spacing:-0.016em}.pk{margin-top:0.94em}.ps{margin-top:1.14em}.py{margin-top:56px}.re{margin-top:1.72em}.rf{line-height:24px}.rg{letter-spacing:0}.si{display:inline-block}.so{margin-bottom:104px}.ss{flex-direction:row}.sv{margin-bottom:0}.sw{margin-right:20px}.tu{max-width:500px}.un{margin-bottom:72px}.uv{padding-top:72px}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (max-width: 1079.98px)">.e{display:none}.ln{margin-top:0px}.rl{margin-left:auto}.rm{text-align:center}.sh{display:inline-block}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (max-width: 903.98px)">.f{display:none}.lm{margin-top:0px}.sg{display:inline-block}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (max-width: 727.98px)">.g{display:none}.lk{margin-top:0px}.ll{margin-right:0px}.sf{display:inline-block}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (max-width: 551.98px)">.h{display:none}.s{display:flex}.t{justify-content:space-between}.bs{width:24px}.cc{margin:0 24px}.cr{height:40px}.cy{margin-bottom:44px}.dk{margin-bottom:32px}.dx{font-size:13px}.dy{line-height:20px}.eh{padding:0px 8px 1px}.fu{margin-bottom:4px}.gw{font-size:32px}.gx{margin-top:1.01em}.gy{margin-bottom:24px}.gz{line-height:38px}.ha{letter-spacing:-0.014em}.hv{align-items:flex-start}.iy{flex-direction:column}.jb{margin-bottom:2px}.jp{margin:24px -24px 0}.jq{padding:0}.kf> *{margin-right:8px}.kg> :last-child{margin-right:24px}.kx{margin-left:0px}.li{margin-top:0px}.lj{margin-right:0px}.ly{margin:0}.mi{border:1px solid #F2F2F2}.mj{border-radius:99em}.mk{padding:0px 16px 0px 12px}.ml{height:38px}.mm{align-items:center}.mo svg{margin-right:8px}.mz{margin-top:32px}.nn{font-size:18px}.no{margin-top:1.56em}.np{line-height:28px}.nq{letter-spacing:-0.003em}.ol{font-size:20px}.om{margin-top:1.2em}.on{line-height:24px}.oo{letter-spacing:0}.pg{margin-top:0.67em}.po{margin-top:1.34em}.pu{margin-top:40px}.qu{font-size:16px}.qv{margin-top:1.23em}.se{display:inline-block}.sk{margin-bottom:96px}.td{margin-bottom:20px}.te{margin-right:0}.ty{max-width:100%}.ub{font-size:24px}.uc{line-height:30px}.ud{letter-spacing:-0.016em}.uj{margin-bottom:64px}.ur{padding-top:48px}.mn:hover{border-color:#E5E5E5}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (min-width: 904px) and (max-width: 1079.98px)">.i{display:none}.bv{width:64px}.cf{margin:0 64px}.cu{height:48px}.db{margin-bottom:52px}.dn{margin-bottom:48px}.ed{font-size:14px}.ee{line-height:20px}.ek{font-size:13px}.el{padding:5px 12px}.fg{display:flex}.fx{margin-bottom:68px}.gb{max-width:680px}.hl{font-size:42px}.hm{margin-top:1.19em}.hn{margin-bottom:32px}.ho{line-height:52px}.hp{letter-spacing:-0.011em}.hy{align-items:center}.jx{border-top:solid 1px #F2F2F2}.jy{border-bottom:solid 1px #F2F2F2}.jz{margin:32px 0 0}.ka{padding:3px 8px}.kl> *{margin-right:24px}.km> :last-child{margin-right:0}.mb{margin:0}.nc{margin-top:40px}.nz{font-size:20px}.oa{margin-top:2.14em}.ob{line-height:32px}.oc{letter-spacing:-0.003em}.ox{font-size:24px}.oy{margin-top:1.95em}.oz{line-height:30px}.pa{letter-spacing:-0.016em}.pj{margin-top:0.94em}.pr{margin-top:1.14em}.px{margin-top:56px}.rb{margin-top:1.72em}.rc{line-height:24px}.rd{letter-spacing:0}.sn{margin-bottom:104px}.st{flex-direction:row}.sx{margin-bottom:0}.sy{margin-right:20px}.tv{max-width:500px}.um{margin-bottom:72px}.uu{padding-top:72px}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (min-width: 728px) and (max-width: 903.98px)">.j{display:none}.w{display:flex}.x{justify-content:space-between}.bu{width:64px}.ce{margin:0 48px}.ct{height:48px}.da{margin-bottom:52px}.dm{margin-bottom:48px}.eb{font-size:13px}.ec{line-height:20px}.ej{padding:0px 8px 1px}.fw{margin-bottom:68px}.ga{max-width:680px}.hg{font-size:42px}.hh{margin-top:1.19em}.hi{margin-bottom:32px}.hj{line-height:52px}.hk{letter-spacing:-0.011em}.hx{align-items:center}.jt{border-top:solid 1px #F2F2F2}.ju{border-bottom:solid 1px #F2F2F2}.jv{margin:32px 0 0}.jw{padding:3px 8px}.kj> *{margin-right:24px}.kk> :last-child{margin-right:0}.ma{margin:0}.nb{margin-top:40px}.nv{font-size:20px}.nw{margin-top:2.14em}.nx{line-height:32px}.ny{letter-spacing:-0.003em}.ot{font-size:24px}.ou{margin-top:1.95em}.ov{line-height:30px}.ow{letter-spacing:-0.016em}.pi{margin-top:0.94em}.pq{margin-top:1.14em}.pw{margin-top:56px}.qy{margin-top:1.72em}.qz{line-height:24px}.ra{letter-spacing:0}.sm{margin-bottom:104px}.su{flex-direction:row}.sz{margin-bottom:0}.ta{margin-right:20px}.tw{max-width:500px}.ul{margin-bottom:72px}.ut{padding-top:72px}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="all and (min-width: 552px) and (max-width: 727.98px)">.k{display:none}.u{display:flex}.v{justify-content:space-between}.bt{width:24px}.cd{margin:0 24px}.cs{height:40px}.cz{margin-bottom:44px}.dl{margin-bottom:32px}.dz{font-size:13px}.ea{line-height:20px}.ei{padding:0px 8px 1px}.fv{margin-bottom:4px}.hb{font-size:32px}.hc{margin-top:1.01em}.hd{margin-bottom:24px}.he{line-height:38px}.hf{letter-spacing:-0.014em}.hw{align-items:flex-start}.iz{flex-direction:column}.jc{margin-bottom:2px}.jr{margin:24px 0 0}.js{padding:0}.kh> *{margin-right:8px}.ki> :last-child{margin-right:8px}.ky{margin-left:0px}.lz{margin:0}.mp{border:1px solid #F2F2F2}.mq{border-radius:99em}.mr{padding:0px 16px 0px 12px}.ms{height:38px}.mt{align-items:center}.mv svg{margin-right:8px}.na{margin-top:32px}.nr{font-size:18px}.ns{margin-top:1.56em}.nt{line-height:28px}.nu{letter-spacing:-0.003em}.op{font-size:20px}.oq{margin-top:1.2em}.or{line-height:24px}.os{letter-spacing:0}.ph{margin-top:0.67em}.pp{margin-top:1.34em}.pv{margin-top:40px}.qw{font-size:16px}.qx{margin-top:1.23em}.sl{margin-bottom:96px}.tb{margin-bottom:20px}.tc{margin-right:0}.tx{max-width:100%}.ue{font-size:24px}.uf{line-height:30px}.ug{letter-spacing:-0.016em}.uk{margin-bottom:64px}.us{padding-top:48px}.mu:hover{border-color:#E5E5E5}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="print">.sc{display:none}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="(orientation: landscape) and (max-width: 903.98px)">.jm{max-height:none}</style><style type="text/css" data-fela-rehydration="572" data-fela-type="RULE" media="(prefers-reduced-motion: no-preference)">.nf{transition:transform 300ms cubic-bezier(0.2, 0, 0.2, 1)}</style></head><body><div id="root"><div class="a b c"><div class="d e f g h i j k"></div><script>document.domain = document.domain;</script><div class="l c"><div class="l m n o c"><div class="p q r s t u v w x i d y z"><a class="du ag dv bf ak b am an ao ap aq ar as at s u w i d q dw z" href="https://rsci.app.link/?%24canonical_url=https%3A%2F%2Fmedium.com%2Fp%2Fa950e6f9eb72&amp;%7Efeature=LoOpenInAppButton&amp;%7Echannel=ShowPostUnderCollection&amp;source=---top_nav_layout_nav----------------------------------" rel="noopener follow">Open in app<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" fill="none" viewBox="0 0 10 10" class="dt"><path fill="currentColor" d="M.985 8.485a.375.375 0 1 0 .53.53zM8.75 1.25h.375A.375.375 0 0 0 8.75.875zM8.375 6.5a.375.375 0 1 0 .75 0zM3.5.875a.375.375 0 1 0 0 .75zm-1.985 8.14 7.5-7.5-.53-.53-7.5 7.5zm6.86-7.765V6.5h.75V1.25zM3.5 1.625h5.25v-.75H3.5z"></path></svg></a><div class="ab q"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="bf b dx dy eh dz ea ei eb ec ej ek ee el em eg eo ep eq er es et eu ev ew ex ey ez fa fb fc fd bm fe ff" data-testid="headerSignUpButton" href="https://medium.com/m/signin?operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------" rel="noopener follow">Sign up</a></span></p><div class="ax l"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSignInButton" href="https://medium.com/m/signin?operation=login&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------" rel="noopener follow">Sign in</a></span></p></div></div></div><div class="p q r ab ac"><div class="ab q ae"><a class="af ag ah ai aj ak al am an ao ap aq ar as at ab" aria-label="Homepage" data-testid="headerMediumLogo" href="https://medium.com/?source=---top_nav_layout_nav----------------------------------" rel="noopener follow"><svg xmlns="http://www.w3.org/2000/svg" width="719" height="160" fill="none" viewBox="0 0 719 160" class="au av aw"><path fill="#242424" d="m174.104 9.734.215-.047V8.02H130.39L89.6 103.89 48.81 8.021H1.472v1.666l.212.047c8.018 1.81 12.09 4.509 12.09 14.242V137.93c0 9.734-4.087 12.433-12.106 14.243l-.212.047v1.671h32.118v-1.665l-.213-.048c-8.018-1.809-12.089-4.509-12.089-14.242V30.586l52.399 123.305h2.972l53.925-126.743V140.75c-.687 7.688-4.721 10.062-11.982 11.701l-.215.05v1.652h55.948v-1.652l-.215-.05c-7.269-1.639-11.4-4.013-12.087-11.701l-.037-116.774h.037c0-9.733 4.071-12.432 12.087-14.242m25.555 75.488c.915-20.474 8.268-35.252 20.606-35.507 3.806.063 6.998 1.312 9.479 3.714 5.272 5.118 7.751 15.812 7.368 31.793zm-.553 5.77h65.573v-.275c-.186-15.656-4.721-27.834-13.466-36.196-7.559-7.227-18.751-11.203-30.507-11.203h-.263c-6.101 0-13.584 1.48-18.909 4.16-6.061 2.807-11.407 7.003-15.855 12.511-7.161 8.874-11.499 20.866-12.554 34.343q-.05.606-.092 1.212a50 50 0 0 0-.065 1.151 85.807 85.807 0 0 0-.094 5.689c.71 30.524 17.198 54.917 46.483 54.917 25.705 0 40.675-18.791 44.407-44.013l-1.886-.664c-6.557 13.556-18.334 21.771-31.738 20.769-18.297-1.369-32.314-19.922-31.042-42.395m139.722 41.359c-2.151 5.101-6.639 7.908-12.653 7.908s-11.513-4.129-15.418-11.63c-4.197-8.053-6.405-19.436-6.405-32.92 0-28.067 8.729-46.22 22.24-46.22 5.657 0 10.111 2.807 12.236 7.704zm43.499 20.008c-8.019-1.897-12.089-4.722-12.089-14.951V1.309l-48.716 14.353v1.757l.299-.024c6.72-.543 11.278.386 13.925 2.83 2.072 1.915 3.082 4.853 3.082 8.987v18.66c-4.803-3.067-10.516-4.56-17.448-4.56-14.059 0-26.909 5.92-36.176 16.672-9.66 11.205-14.767 26.518-14.767 44.278-.003 31.72 15.612 53.039 38.851 53.039 13.595 0 24.533-7.449 29.54-20.013v16.865h43.711v-1.746zM424.1 19.819c0-9.904-7.468-17.374-17.375-17.374-9.859 0-17.573 7.632-17.573 17.374s7.721 17.374 17.573 17.374c9.907 0 17.375-7.47 17.375-17.374m11.499 132.546c-8.019-1.897-12.089-4.722-12.089-14.951h-.035V43.635l-43.714 12.551v1.705l.263.024c9.458.842 12.047 4.1 12.047 15.152v81.086h43.751v-1.746zm112.013 0c-8.018-1.897-12.089-4.722-12.089-14.951V43.635l-41.621 12.137v1.71l.246.026c7.733.813 9.967 4.257 9.967 15.36v59.279c-2.578 5.102-7.415 8.131-13.274 8.336-9.503 0-14.736-6.419-14.736-18.073V43.638l-43.714 12.55v1.703l.262.024c9.459.84 12.05 4.097 12.05 15.152v50.17a56.3 56.3 0 0 0 .91 10.444l.787 3.423c3.701 13.262 13.398 20.197 28.59 20.197 12.868 0 24.147-7.966 29.115-20.43v17.311h43.714v-1.747zm169.818 1.788v-1.749l-.213-.05c-8.7-2.006-12.089-5.789-12.089-13.49v-63.79c0-19.89-11.171-31.761-29.883-31.761-13.64 0-25.141 7.882-29.569 20.16-3.517-13.01-13.639-20.16-28.606-20.16-13.146 0-23.449 6.938-27.869 18.657V43.643L545.487 55.68v1.715l.263.024c9.345.829 12.047 4.181 12.047 14.95v81.784h40.787v-1.746l-.215-.053c-6.941-1.631-9.181-4.606-9.181-12.239V66.998c1.836-4.289 5.537-9.37 12.853-9.37 9.086 0 13.692 6.296 13.692 18.697v77.828h40.797v-1.746l-.215-.053c-6.94-1.631-9.18-4.606-9.18-12.239V75.066a42 42 0 0 0-.578-7.26c1.947-4.661 5.86-10.177 13.475-10.177 9.214 0 13.691 6.114 13.691 18.696v77.828z"></path></svg></a><div class="ax h"><div class="ab ay az ba bb q bc bd"><div class="bm" aria-hidden="false" aria-describedby="searchResults" aria-labelledby="searchResults"></div><div class="bn bo ab"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M4.092 11.06a6.95 6.95 0 1 1 13.9 0 6.95 6.95 0 0 1-13.9 0m6.95-8.05a8.05 8.05 0 1 0 5.13 14.26l3.75 3.75a.56.56 0 1 0 .79-.79l-3.73-3.73A8.05 8.05 0 0 0 11.042 3z" clip-rule="evenodd"></path></svg></div><input role="combobox" aria-controls="searchResults" aria-expanded="false" aria-label="search" data-testid="headerSearchInput" tabindex="0" class="ay be bf bg z bh bi bj bk bl" placeholder="Search" value=""/></div></div></div><div class="h k w fg fh"><div class="fi ab"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerWriteButton" href="https://medium.com/m/signin?operation=register&amp;redirect=https%3A%2F%2Fmedium.com%2Fnew-story&amp;source=---top_nav_layout_nav-----------------------new_post_topnav-----------" rel="noopener follow"><div class="bf b bg z du fj fk ab q fl fm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" aria-label="Write"><path fill="currentColor" d="M14 4a.5.5 0 0 0 0-1zm7 6a.5.5 0 0 0-1 0zm-7-7H4v1h10zM3 4v16h1V4zm1 17h16v-1H4zm17-1V10h-1v10zm-1 1a1 1 0 0 0 1-1h-1zM3 20a1 1 0 0 0 1 1v-1zM4 3a1 1 0 0 0-1 1h1z"></path><path stroke="currentColor" d="m17.5 4.5-8.458 8.458a.25.25 0 0 0-.06.098l-.824 2.47a.25.25 0 0 0 .316.316l2.47-.823a.25.25 0 0 0 .098-.06L19.5 6.5m-2-2 2.323-2.323a.25.25 0 0 1 .354 0l1.646 1.646a.25.25 0 0 1 0 .354L19.5 6.5m-2-2 2 2"></path></svg><div class="dt l">Write</div></div></a></span></div></div><div class="k j i d"><div class="fi ab"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSearchButton" href="https://medium.com/search?source=---top_nav_layout_nav----------------------------------" rel="noopener follow"><div class="bf b bg z du fj fk ab q fl fm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" aria-label="Search"><path fill="currentColor" fill-rule="evenodd" d="M4.092 11.06a6.95 6.95 0 1 1 13.9 0 6.95 6.95 0 0 1-13.9 0m6.95-8.05a8.05 8.05 0 1 0 5.13 14.26l3.75 3.75a.56.56 0 1 0 .79-.79l-3.73-3.73A8.05 8.05 0 0 0 11.042 3z" clip-rule="evenodd"></path></svg></div></a></div></div><div class="fi h k j"><div class="ab q"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="bf b dx dy eh dz ea ei eb ec ej ek ee el em eg eo ep eq er es et eu ev ew ex ey ez fa fb fc fd bm fe ff" data-testid="headerSignUpButton" href="https://medium.com/m/signin?operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------" rel="noopener follow">Sign up</a></span></p><div class="ax l"><p class="bf b dx dy dz ea eb ec ed ee ef eg du"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerSignInButton" href="https://medium.com/m/signin?operation=login&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=post_page---top_nav_layout_nav-----------------------global_nav-----------" rel="noopener follow">Sign in</a></span></p></div></div></div><div class="l" aria-hidden="false"><button class="ay fn am ab q ao fo fp fq" aria-label="user options menu" data-testid="headerUserIcon"><div class="l fj"><img alt="" class="l fd by bz ca cx" src="https://miro.medium.com/v2/resize:fill:64:64/1*dmbNkD5D-u45r44go_cf0g.png" width="32" height="32" loading="lazy" role="presentation"/><div class="fr by l bz ca fs n ay ft"></div></div></button></div></div></div><div class="l"><div class="fu fv fw fx fy l"><div class="ab cb"><div class="ci bh fz ga gb gc"></div></div><article><div class="l"><div class="l"><span class="l"></span><section><div><div class="fs gi gj gk gl gm"></div><div class="gn go gp gq gr"><div class="ab cb"><div class="ci bh fz ga gb gc"><div><h1 id="4e92" class="pw-post-title gs gt gu bf gv gw gx gy gz ha hb hc hd he hf hg hh hi hj hk hl hm hn ho hp hq hr hs ht hu bk" data-testid="storyTitle">Custom modifiers in Jetpack Compose</h1><div><div class="speechify-ignore ab cp"><div class="speechify-ignore bh l"><div class="hv hw hx hy hz ab"><div><div class="ab ia"><div><div class="bm" aria-hidden="false"><a href="https://medium.com/@siddh.gupta99?source=post_page---byline--a950e6f9eb72--------------------------------" rel="noopener follow"><div class="l ib ic by id ie"><div class="l fj"><img alt="Siddharth Gupta" class="l fd by dd de cx" src="https://miro.medium.com/v2/resize:fill:88:88/1*6rI29yuZZDr-3XD0qlJ-RQ.jpeg" width="44" height="44" loading="lazy" data-testid="authorPhoto"/><div class="if by l dd de fs n ig ft"></div></div></div></a></div></div><div class="ih ab fj"><div><div class="bm" aria-hidden="false"><a href="https://proandroiddev.com/?source=post_page---byline--a950e6f9eb72--------------------------------" rel="noopener ugc nofollow"><div class="l ii ij by id ik"><div class="l fj"><img alt="ProAndroidDev" class="l fd by br il cx" src="https://miro.medium.com/v2/resize:fill:48:48/1*XVtdl45m8YaYrPI4buJ5yQ.png" width="24" height="24" loading="lazy" data-testid="publicationPhoto"/><div class="if by l br il fs n ig ft"></div></div></div></a></div></div></div></div></div><div class="bn bh l"><div class="ab"><div style="flex:1"><span class="bf b bg z bk"><div class="im ab q"><div class="ab q in"><div class="ab q"><div><div class="bm" aria-hidden="false"><p class="bf b io ip bk"><a class="af ag ah ai aj ak al am an ao ap aq ar iq" data-testid="authorName" href="https://medium.com/@siddh.gupta99?source=post_page---byline--a950e6f9eb72--------------------------------" rel="noopener follow">Siddharth Gupta</a></p></div></div></div><span class="ir is" aria-hidden="true"><span class="bf b bg z du">·</span></span><p class="bf b io ip du"><span><a class="it iu ah ai aj ak al am an ao ap aq ar ex iv iw" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fuser%2Fe072cea221fc&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=post_page-e072cea221fc--byline--a950e6f9eb72---------------------post_header-----------" rel="noopener follow">Follow</a></span></p></div></div></span></div></div><div class="l ix"><span class="bf b bg z du"><div class="ab cn iy iz ja"><div class="jb jc ab"><div class="bf b bg z du ab jd"><span class="je l ix">Published in</span><div><div class="l" aria-hidden="false"><a class="af ag ah ai aj ak al am an ao ap aq ar iq ab q" data-testid="publicationName" href="https://proandroiddev.com/?source=post_page---byline--a950e6f9eb72--------------------------------" rel="noopener ugc nofollow"><p class="bf b bg z jf jg jh ji jj jk jl jm bk">ProAndroidDev</p></a></div></div></div><div class="h k"><span class="ir is" aria-hidden="true"><span class="bf b bg z du">·</span></span></div></div><span class="bf b bg z du"><div class="ab ae"><span data-testid="storyReadTime">5 min read</span><div class="jn jo l" aria-hidden="true"><span class="l" aria-hidden="true"><span class="bf b bg z du">·</span></span></div>5 days ago</div></span></div></span></div></div></div><div class="ab cp jp jq jr js jt ju jv jw jx jy jz ka kb kc kd ke"><div class="h k w fg fh q"><div class="ku l"><div class="ab q kv kw"><div class="pw-multi-vote-icon fj je kx ky kz"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerClapButton" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fproandroiddev%2Fa950e6f9eb72&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=---header_actions--a950e6f9eb72---------------------clap_footer-----------" rel="noopener follow"><div><div class="bm" aria-hidden="false"><div class="la ao lb lc ld le am lf lg lh kz"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l li lj lk ll lm ln lo"><p class="bf b dv z du"><span class="lp">--</span></p></div></div></div><div><div class="bm" aria-hidden="false"><button class="ao la lq lr ab q fk ls lt" aria-label="responses"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="lu"><path d="M18.006 16.803c1.533-1.456 2.234-3.325 2.234-5.321C20.24 7.357 16.709 4 12.191 4S4 7.357 4 11.482c0 4.126 3.674 7.482 8.191 7.482.817 0 1.622-.111 2.393-.327.231.2.48.391.744.559 1.06.693 2.203 1.044 3.399 1.044.224-.008.4-.112.486-.287a.49.49 0 0 0-.042-.518c-.495-.67-.845-1.364-1.04-2.057a4 4 0 0 1-.125-.598zm-3.122 1.055-.067-.223-.315.096a8 8 0 0 1-2.311.338c-4.023 0-7.292-2.955-7.292-6.587 0-3.633 3.269-6.588 7.292-6.588 4.014 0 7.112 2.958 7.112 6.593 0 1.794-.608 3.469-2.027 4.72l-.195.168v.255c0 .056 0 .151.016.295.025.231.081.478.154.733.154.558.398 1.117.722 1.659a5.3 5.3 0 0 1-2.165-.845c-.276-.176-.714-.383-.941-.59z"></path></svg></button></div></div></div><div class="ab q kf kg kh ki kj kk kl km kn ko kp kq kr ks kt"><div class="lv k j i d"></div><div class="h k"><div><div class="bm" aria-hidden="false"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="headerBookmarkButton" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fbookmark%2Fp%2Fa950e6f9eb72&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=---header_actions--a950e6f9eb72---------------------bookmark_footer-----------" rel="noopener follow"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none" viewBox="0 0 25 25" class="du lw" aria-label="Add to list bookmark button"><path fill="currentColor" d="M18 2.5a.5.5 0 0 1 1 0V5h2.5a.5.5 0 0 1 0 1H19v2.5a.5.5 0 1 1-1 0V6h-2.5a.5.5 0 0 1 0-1H18zM7 7a1 1 0 0 1 1-1h3.5a.5.5 0 0 0 0-1H8a2 2 0 0 0-2 2v14a.5.5 0 0 0 .805.396L12.5 17l5.695 4.396A.5.5 0 0 0 19 21v-8.5a.5.5 0 0 0-1 0v7.485l-5.195-4.012a.5.5 0 0 0-.61 0L7 19.985z"></path></svg></a></span></div></div></div><div class="fd lx cn"><div class="l ae"><div class="ab cb"><div class="ly lz ma mb mc md ci bh"><div class="ab"><div class="bm bh" aria-hidden="false"><div><div class="bm" aria-hidden="false"><button aria-label="Listen" data-testid="audioPlayButton" class="af fk ah ai aj ak al me an ao ap ex mf mg lt mh mi mj mk ml s mm mn mo mp mq mr ms u mt mu mv"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M3 12a9 9 0 1 1 18 0 9 9 0 0 1-18 0m9-10C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2m3.376 10.416-4.599 3.066a.5.5 0 0 1-.777-.416V8.934a.5.5 0 0 1 .777-.416l4.599 3.066a.5.5 0 0 1 0 .832" clip-rule="evenodd"></path></svg><div class="j i d"><p class="bf b bg z du">Listen</p></div></button></div></div></div></div></div></div></div></div><div class="bm" aria-hidden="false" aria-describedby="postFooterSocialMenu" aria-labelledby="postFooterSocialMenu"><div><div class="bm" aria-hidden="false"><button aria-controls="postFooterSocialMenu" aria-expanded="false" aria-label="Share Post" data-testid="headerSocialShareButton" class="af fk ah ai aj ak al me an ao ap ex mf mg lt mh mi mj mk ml s mm mn mo mp mq mr ms u mt mu mv"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.218 4.931a.4.4 0 0 1-.118.132l.012.006a.45.45 0 0 1-.292.074.5.5 0 0 1-.3-.13l-2.02-2.02v7.07c0 .28-.23.5-.5.5s-.5-.22-.5-.5v-7.04l-2 2a.45.45 0 0 1-.57.04h-.02a.4.4 0 0 1-.16-.3.4.4 0 0 1 .1-.32l2.8-2.8a.5.5 0 0 1 .7 0l2.8 2.79a.42.42 0 0 1 .068.498m-.106.138.008.004v-.01zM16 7.063h1.5a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-11c-1.1 0-2-.9-2-2v-10a2 2 0 0 1 2-2H8a.5.5 0 0 1 .35.15.5.5 0 0 1 .15.35.5.5 0 0 1-.15.35.5.5 0 0 1-.35.15H6.4c-.5 0-.9.4-.9.9v10.2a.9.9 0 0 0 .9.9h11.2c.5 0 .9-.4.9-.9v-10.2c0-.5-.4-.9-.9-.9H16a.5.5 0 0 1 0-1" clip-rule="evenodd"></path></svg><div class="j i d"><p class="bf b bg z du">Share</p></div></button></div></div></div></div></div></div></div></div></div><figure class="mz na nb nc nd ne mw mx paragraph-image"><div role="button" tabindex="0" class="nf ng fj nh bh ni"><div class="mw mx my"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 1100w, https://miro.medium.com/v2/resize:fit:1400/format:webp/1*Oe-DGannPg34NnFtp02TjA.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*Oe-DGannPg34NnFtp02TjA.png 640w, https://miro.medium.com/v2/resize:fit:720/1*Oe-DGannPg34NnFtp02TjA.png 720w, https://miro.medium.com/v2/resize:fit:750/1*Oe-DGannPg34NnFtp02TjA.png 750w, https://miro.medium.com/v2/resize:fit:786/1*Oe-DGannPg34NnFtp02TjA.png 786w, https://miro.medium.com/v2/resize:fit:828/1*Oe-DGannPg34NnFtp02TjA.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*Oe-DGannPg34NnFtp02TjA.png 1100w, https://miro.medium.com/v2/resize:fit:1400/1*Oe-DGannPg34NnFtp02TjA.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px"/><img alt="" class="bh md nj c" width="700" height="700" loading="eager" role="presentation"/></picture></div></div></figure><p id="3a16" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the appearance, behaviour, and layout of composable functions without changing their core implementation.</p><h1 id="a300" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">Key aspects of modifiers:</h1><ul class=""><li id="87fb" class="nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh pl pm pn bk"><strong class="nm gv">Chainable:</strong> Modifiers can be chained together, allowing for multiple modifications to be applied sequentially.</li><li id="6e91" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">Reusable:</strong> Custom modifiers can be created and reused across different components, promoting code reusability.</li><li id="93cf" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">Extensible:</strong> Developers can create their own custom modifiers to add specific functionality.</li></ul><p id="2a7e" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">The Reusable and Extensible aspects is what make modifiers super powerful. Hence in this blog we’ll be looking at how to create custom modifiers.</p><h1 id="ce89" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">Three Ways</h1><ol class=""><li id="d877" class="nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh pt pm pn bk">composed { }</li><li id="12ba" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pt pm pn bk">@composable modifier factory</li><li id="bde2" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pt pm pn bk">Modifier.Node API</li></ol><h1 id="9be4" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">Using composed() to Create Custom Modifiers</h1><p id="a8b0" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">The composed() function is a convenient way to create custom modifiers in Jetpack Compose. It allows you to define a modifier that can contain composable content.</p><p id="543f" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Here’s a basic structure of using composed():</p><pre class="pu pv pw px py pz qa qb bp qc bb bk"><span id="b025" class="qd oj gu qa b bg qe qf l qg qh">fun Modifier.customModifier(<br/> // parameters<br/>) = composed {<br/> // Your custom modifier logic here<br/> // Can include other composables<br/> this.then(<br/> // Additional modifiers<br/> )<br/>}</span></pre><p id="c329" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Key points about using composed():</p><ul class=""><li id="310c" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pl pm pn bk"><strong class="nm gv">Composable context:</strong> Inside composed{}, you have access to the composable context, allowing you to use other @Composable functions.</li><li id="43a0" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">State observation:</strong> You can observe state and trigger recomposition when needed.</li><li id="0cf6" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">Chaining:</strong> Use this.then() to chain additional modifiers.</li></ul><p id="2976" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Example of a custom modifier using composed():</p><figure class="pu pv pw px py ne"><div class="qi jf l fj"><div class="qj qk l"></div></div></figure><p id="da7e" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">This example creates a shimmer effect modifier that can be applied to any composable to add a shimmering animation.</p><h1 id="cc39" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">Using @Composable Modifier Factory to Create Custom Modifiers</h1><p id="d774" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">Another approach to creating custom modifiers in Jetpack Compose is using @Composable modifier factories. This method allows you to create modifiers that can use other @Composable functions and observe state changes.</p><p id="e025" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Here’s the basic structure of a @Composable modifier factory:</p><pre class="pu pv pw px py pz qa qb bp qc bb bk"><span id="3292" class="qd oj gu qa b bg qe qf l qg qh">@Composable<br/>fun Modifier.customModifier(<br/> // parameters<br/>): Modifier {<br/> // Your custom modifier logic here<br/> return this.then(<br/> // Additional modifiers<br/> )<br/>}</span></pre><p id="9e31" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Key points about using @Composable modifier factories:</p><ul class=""><li id="859e" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pl pm pn bk"><strong class="nm gv">Composable context:</strong> The function is marked with @Composable, giving you access to other composable functions and state.</li><li id="7ff0" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">Return type:</strong> The function explicitly returns a Modifier.</li><li id="4258" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk"><strong class="nm gv">Flexibility:</strong> You can use remember, derivedStateOf, and other composable functions within the modifier.</li></ul><p id="9c50" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Example of a custom modifier using @Composable modifier factory:</p><figure class="pu pv pw px py ne"><div class="qi jf l fj"><div class="qj qk l"></div></div></figure><p id="c41c" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">This example creates a pulsating scale effect modifier that can be applied to any composable to add a pulsating animation. The scale and duration of the pulse can be customised through parameters.</p><blockquote class="ql qm qn"><p id="d86f" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk"><em class="gu">This is an excellent </em><a class="af qp" href="https://engineering.teknasyon.com/composable-modifier-vs-composed-factory-in-jetpack-compose-6cbb675b0e7b" rel="noopener ugc nofollow" target="_blank"><em class="gu">article</em></a><em class="gu"> which explains the key differences b/w the 2 approaches. Here is the summary:</em></p><p id="989e" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk"><em class="gu">1. </em><strong class="nm gv">Extractability</strong>: CMF is limited to use within the Composition scope, while composed() can be extracted and used more flexibly.</p><p id="6dd1" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">2. <strong class="nm gv">CompositionLocal resolution</strong>: CMF resolves CompositionLocal values at the call site, while composed() resolves them at the usage site.</p><p id="8e14" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">3. <strong class="nm gv">State resolution</strong>: CMF resolves state only once at the call site, while composed() resolves state at the usage site for each Layout.</p><p id="db31" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">4. <strong class="nm gv">Performance</strong>: CMF performs better than composed() due to avoiding the expensive materialize() call.</p></blockquote><h1 id="cb56" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">The Recommended Way: New Modifier.Node API</h1><p id="17c2" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">As we can see above, creating custom modifiers using <code class="cx qq qr qs qa b">composed { }</code> makes more sense than using the <strong class="nm gv">CMF</strong> approach. Using <strong class="nm gv">CMF</strong> is ideal when you need inline modifiers or extract a modifier for using it in only one component. On the other hand, <strong class="nm gv">composed</strong> is useful when designing generic modifiers.</p><p id="6a9e" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">But here’s the catch, the <strong class="nm gv">composed</strong> way has few performance issues and the new recommended way of creating custom modifiers is to use the Modifier.Node API.</p><blockquote class="ql qm qn"><p id="29d0" class="nk nl qo nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk"><strong class="nm gv"><em class="gu">Compose 1.3</em></strong><em class="gu"> introduced the </em>Modifier.Node<em class="gu"> API where the team has migrated all the pre-defined modifiers to this new API. I would highly recommend to watch </em><a class="af qp" href="https://www.youtube.com/watch?v=BjGX2RftXsU" rel="noopener ugc nofollow" target="_blank"><em class="gu">this</em></a><em class="gu"> youtube video of Android Dev Summit which explains why this change has been done.</em></p></blockquote><p id="1636" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">So if you want the best of both worlds — performance, extractability, skippability, reusable modifiers, use Modifier.Node API</p><p id="261d" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">There are three parts to implementing a custom modifier using Modifier.Node:</p><ul class=""><li id="0337" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pl pm pn bk">A <code class="cx qq qr qs qa b">Modifier.Node</code> implementation that holds the logic and state of your modifier.</li><li id="5309" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk">A <code class="cx qq qr qs qa b">ModifierNodeElement</code> that creates and updates modifier node instances.</li><li id="c37c" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk">An optional modifier factory as detailed above.</li></ul><p id="cecb" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk"><code class="cx qq qr qs qa b">ModifierNodeElement</code> classes are stateless and new instances are allocated each recomposition, whereas <code class="cx qq qr qs qa b">Modifier.Node</code> classes can be stateful and will survive across multiple recompositions, and can even be reused.</p><p id="cc01" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Here is the very basic example of drawing a circle of specific color as shared in the official documentation.</p><figure class="pu pv pw px py ne"><div class="qi jf l fj"><div class="qj qk l"></div></div></figure><p id="841d" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Let’s breakdown to our process</p><h2 id="3a9a" class="qt oj gu bf ok qu qv dy oo qw qx ea os nv qy qz ra nz rb rc rd od re rf rg rh bk"><strong class="al">Modifier.Node:</strong></h2><p id="f295" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">The first step is to create a class which implements the <code class="cx qq qr qs qa b">Modifier.Node</code> along with <code class="cx qq qr qs qa b">DrawModifierNode</code>. There are multiple factory nodes which compose provides out of the box. Here we want to draw something hence we are using the <code class="cx qq qr qs qa b">DrawModifierNode</code>. If we wanted to do something with user inputs or gestures we might want to use <code class="cx qq qr qs qa b">PointerInputModifierNode</code></p><figure class="pu pv pw px py ne mw mx paragraph-image"><div role="button" tabindex="0" class="nf ng fj nh bh ni"><div class="mw mx ri"><picture><source srcSet="https://miro.medium.com/v2/resize:fit:640/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 640w, https://miro.medium.com/v2/resize:fit:720/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 720w, https://miro.medium.com/v2/resize:fit:750/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 750w, https://miro.medium.com/v2/resize:fit:786/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 786w, https://miro.medium.com/v2/resize:fit:828/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 828w, https://miro.medium.com/v2/resize:fit:1100/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 1100w, https://miro.medium.com/v2/resize:fit:1400/format:webp/1*ybo1ri0Ouh63eDGq0R0tsw.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px" type="image/webp"/><source data-testid="og" srcSet="https://miro.medium.com/v2/resize:fit:640/1*ybo1ri0Ouh63eDGq0R0tsw.png 640w, https://miro.medium.com/v2/resize:fit:720/1*ybo1ri0Ouh63eDGq0R0tsw.png 720w, https://miro.medium.com/v2/resize:fit:750/1*ybo1ri0Ouh63eDGq0R0tsw.png 750w, https://miro.medium.com/v2/resize:fit:786/1*ybo1ri0Ouh63eDGq0R0tsw.png 786w, https://miro.medium.com/v2/resize:fit:828/1*ybo1ri0Ouh63eDGq0R0tsw.png 828w, https://miro.medium.com/v2/resize:fit:1100/1*ybo1ri0Ouh63eDGq0R0tsw.png 1100w, https://miro.medium.com/v2/resize:fit:1400/1*ybo1ri0Ouh63eDGq0R0tsw.png 1400w" sizes="(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 700px"/><img alt="" class="bh md nj c" width="700" height="869" loading="lazy" role="presentation"/></picture></div></div><figcaption class="rj ff rk mw mx rl rm bf b bg z du">Available nodes to override (image taken from Android Documentation)</figcaption></figure><h2 id="6582" class="qt oj gu bf ok qu qv dy oo qw qx ea os nv qy qz ra nz rb rc rd od re rf rg rh bk">ModifierNodeElement<strong class="al">:</strong></h2><p id="da4f" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">A <code class="cx qq qr qs qa b">ModifierNodeElement</code> is an immutable class that holds the data to create or update your custom modifier:</p><pre class="pu pv pw px py pz qa qb bp qc bb bk"><span id="fa41" class="qd oj gu qa b bg qe qf l qg qh">// ModifierNodeElement<br/>private data class CircleElement(val color: Color) : ModifierNodeElement&lt;CircleNode&gt;() {<br/> override fun create() = CircleNode(color)<br/><br/> override fun update(node: CircleNode) {<br/> node.color = color<br/> }<br/>}</span></pre><p id="9d94" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk"><code class="cx qq qr qs qa b">ModifierNodeElement</code> implementations need to override the following methods:</p><ol class=""><li id="7f0c" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pt pm pn bk"><code class="cx qq qr qs qa b">create</code>: This is the function that instantiates your modifier node. This gets called to create the node when your modifier is first applied. Usually, this amounts to constructing the node and configuring it with the parameters that were passed in to the modifier factory.</li><li id="1c8f" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pt pm pn bk"><code class="cx qq qr qs qa b">update</code>: This function is called whenever this modifier is provided in the same spot this node already exists, but a property has changed. This is determined by the <code class="cx qq qr qs qa b">equals</code> method of the class. The modifier node that was previously created is sent as a parameter to the <code class="cx qq qr qs qa b">update</code> call. At this point, you should update the nodes&#x27; properties to correspond with the updated parameters. The ability for nodes to be reused this way is key to the performance gains that <code class="cx qq qr qs qa b">Modifier.Node</code> brings; therefore, you must update the existing node rather than creating a new one in the <code class="cx qq qr qs qa b">update</code> method. In our circle example, the color of the node is updated.</li></ol><p id="7474" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Additionally, <code class="cx qq qr qs qa b">ModifierNodeElement</code> implementations also need to implement <code class="cx qq qr qs qa b">equals</code> and <code class="cx qq qr qs qa b">hashCode</code>. <code class="cx qq qr qs qa b">update</code> will only get called if an equals comparison with the previous element returns false.</p><h2 id="aa97" class="qt oj gu bf ok qu qv dy oo qw qx ea os nv qy qz ra nz rb rc rd od re rf rg rh bk">Modifier Factory:</h2><p id="c1dc" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">This is the public API surface of your modifier. Most implementations simply create the modifier element and add it to the modifier chain:</p><pre class="pu pv pw px py pz qa qb bp qc bb bk"><span id="c101" class="qd oj gu qa b bg qe qf l qg qh">// Modifier factory<br/>fun Modifier.circle(color: Color) = this then CircleElement(color)</span></pre><h1 id="bb1e" class="oi oj gu bf ok ol om on oo op oq or os ot ou ov ow ox oy oz pa pb pc pd pe pf bk">Summary</h1><p id="cb80" class="pw-post-body-paragraph nk nl gu nm b nn pg np nq nr ph nt nu nv pi nx ny nz pj ob oc od pk of og oh gn bk">In this blog post, we’ve explored the power and flexibility of custom modifiers in Jetpack Compose. We’ve covered three main approaches to creating custom modifiers:</p><ol class=""><li id="7cb4" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pt pm pn bk">Using the Composable Modifier Function (CMF)</li><li id="9fb4" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pt pm pn bk">Using the composed { } function</li><li id="d99e" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pt pm pn bk">Using the new Modifier.Node API (recommended)</li></ol><p id="c6ae" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">We’ve learned that while CMF and composed { } methods have their uses, the Modifier.Node API is now the recommended approach for creating custom modifiers. This new API offers better performance, reusability, and extensibility.</p><p id="a8cb" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">Key takeaways:</p><ul class=""><li id="2a47" class="nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh pl pm pn bk">The <em class="qo">Modifier.Node API</em> consists of three main parts: a Modifier.Node implementation, a ModifierNodeElement, and an optional modifier factory.</li><li id="17a8" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk">There are various types of modifier nodes available for different purposes, such as DrawModifierNode, LayoutModifierNode, and PointerInputModifierNode.</li><li id="ba7e" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk">The ModifierNodeElement is responsible for creating and updating modifier node instances, which can be stateful and survive across recompositions.</li><li id="b907" class="nk nl gu nm b nn po np nq nr pp nt nu nv pq nx ny nz pr ob oc od ps of og oh pl pm pn bk">The modifier factory provides a clean, public API for using your custom modifier.</li></ul><p id="52ba" class="pw-post-body-paragraph nk nl gu nm b nn no np nq nr ns nt nu nv nw nx ny nz oa ob oc od oe of og oh gn bk">By mastering custom modifiers, especially using the Modifier.Node API, you can create more efficient, reusable, and powerful UI components in your Jetpack Compose applications.</p></div></div></div></div></section></div></div></article></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="rn ro ab ja"><div class="rp ab"><a class="rq ay am ao" href="https://medium.com/tag/android?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><div class="rr fj cx rs ge rt ru bf b bg z bk rv">Android</div></a></div><div class="rp ab"><a class="rq ay am ao" href="https://medium.com/tag/jetpack-compose?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><div class="rr fj cx rs ge rt ru bf b bg z bk rv">Jetpack Compose</div></a></div><div class="rp ab"><a class="rq ay am ao" href="https://medium.com/tag/apps?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><div class="rr fj cx rs ge rt ru bf b bg z bk rv">Apps</div></a></div><div class="rp ab"><a class="rq ay am ao" href="https://medium.com/tag/development?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><div class="rr fj cx rs ge rt ru bf b bg z bk rv">Development</div></a></div><div class="rp ab"><a class="rq ay am ao" href="https://medium.com/tag/tech?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><div class="rr fj cx rs ge rt ru bf b bg z bk rv">Tech</div></a></div></div></div></div><div class="l"></div><footer class="rw rx ry rz sa ab q sb ik c"><div class="l ae"><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="ab cp sc"><div class="ab q kv"><div class="sd l"><span class="l se sf sg e d"><div class="ab q kv kw"><div class="pw-multi-vote-icon fj je kx ky kz"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerClapButton" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fproandroiddev%2Fa950e6f9eb72&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=---footer_actions--a950e6f9eb72---------------------clap_footer-----------" rel="noopener follow"><div><div class="bm" aria-hidden="false"><div class="la ao lb lc ld le am lf lg lh kz"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l li lj lk ll lm ln lo"><p class="bf b dv z du"><span class="lp">--</span></p></div></div></span><span class="l h g f sh si"><div class="ab q kv kw"><div class="pw-multi-vote-icon fj je kx ky kz"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerClapButton" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fvote%2Fproandroiddev%2Fa950e6f9eb72&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=---footer_actions--a950e6f9eb72---------------------clap_footer-----------" rel="noopener follow"><div><div class="bm" aria-hidden="false"><div class="la ao lb lc ld le am lf lg lh kz"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-label="clap"><path fill-rule="evenodd" d="M11.37.828 12 3.282l.63-2.454zM13.916 3.953l1.523-2.112-1.184-.39zM8.589 1.84l1.522 2.112-.337-2.501zM18.523 18.92c-.86.86-1.75 1.246-2.62 1.33a6 6 0 0 0 .407-.372c2.388-2.389 2.86-4.951 1.399-7.623l-.912-1.603-.79-1.672c-.26-.56-.194-.98.203-1.288a.7.7 0 0 1 .546-.132c.283.046.546.231.728.5l2.363 4.157c.976 1.624 1.141 4.237-1.324 6.702m-10.999-.438L3.37 14.328a.828.828 0 0 1 .585-1.408.83.83 0 0 1 .585.242l2.158 2.157a.365.365 0 0 0 .516-.516l-2.157-2.158-1.449-1.449a.826.826 0 0 1 1.167-1.17l3.438 3.44a.363.363 0 0 0 .516 0 .364.364 0 0 0 0-.516L5.293 9.513l-.97-.97a.826.826 0 0 1 0-1.166.84.84 0 0 1 1.167 0l.97.968 3.437 3.436a.36.36 0 0 0 .517 0 .366.366 0 0 0 0-.516L6.977 7.83a.82.82 0 0 1-.241-.584.82.82 0 0 1 .824-.826c.219 0 .43.087.584.242l5.787 5.787a.366.366 0 0 0 .587-.415l-1.117-2.363c-.26-.56-.194-.98.204-1.289a.7.7 0 0 1 .546-.132c.283.046.545.232.727.501l2.193 3.86c1.302 2.38.883 4.59-1.277 6.75-1.156 1.156-2.602 1.627-4.19 1.367-1.418-.236-2.866-1.033-4.079-2.246M10.75 5.971l2.12 2.12c-.41.502-.465 1.17-.128 1.89l.22.465-3.523-3.523a.8.8 0 0 1-.097-.368c0-.22.086-.428.241-.584a.847.847 0 0 1 1.167 0m7.355 1.705c-.31-.461-.746-.758-1.23-.837a1.44 1.44 0 0 0-1.11.275c-.312.24-.505.543-.59.881a1.74 1.74 0 0 0-.906-.465 1.47 1.47 0 0 0-.82.106l-2.182-2.182a1.56 1.56 0 0 0-2.2 0 1.54 1.54 0 0 0-.396.701 1.56 1.56 0 0 0-2.21-.01 1.55 1.55 0 0 0-.416.753c-.624-.624-1.649-.624-2.237-.037a1.557 1.557 0 0 0 0 2.2c-.239.1-.501.238-.715.453a1.56 1.56 0 0 0 0 2.2l.516.515a1.556 1.556 0 0 0-.753 2.615L7.01 19c1.32 1.319 2.909 2.189 4.475 2.449q.482.08.971.08c.85 0 1.653-.198 2.393-.579.231.033.46.054.686.054 1.266 0 2.457-.52 3.505-1.567 2.763-2.763 2.552-5.734 1.439-7.586z" clip-rule="evenodd"></path></svg></div></div></div></a></span></div><div class="pw-multi-vote-count l li lj lk ll lm ln lo"><p class="bf b dv z du"><span class="lp">--</span></p></div></div></span></div><div class="bq ab"><div><div class="bm" aria-hidden="false"><button class="ao la lq lr ab q fk ls lt" aria-label="responses"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" class="lu"><path d="M18.006 16.803c1.533-1.456 2.234-3.325 2.234-5.321C20.24 7.357 16.709 4 12.191 4S4 7.357 4 11.482c0 4.126 3.674 7.482 8.191 7.482.817 0 1.622-.111 2.393-.327.231.2.48.391.744.559 1.06.693 2.203 1.044 3.399 1.044.224-.008.4-.112.486-.287a.49.49 0 0 0-.042-.518c-.495-.67-.845-1.364-1.04-2.057a4 4 0 0 1-.125-.598zm-3.122 1.055-.067-.223-.315.096a8 8 0 0 1-2.311.338c-4.023 0-7.292-2.955-7.292-6.587 0-3.633 3.269-6.588 7.292-6.588 4.014 0 7.112 2.958 7.112 6.593 0 1.794-.608 3.469-2.027 4.72l-.195.168v.255c0 .056 0 .151.016.295.025.231.081.478.154.733.154.558.398 1.117.722 1.659a5.3 5.3 0 0 1-2.165-.845c-.276-.176-.714-.383-.941-.59z"></path></svg></button></div></div></div></div><div class="ab q"><div class="sj l ix"><div><div class="bm" aria-hidden="false"><span><a class="af ag ah ai aj ak al am an ao ap aq ar as at" data-testid="footerBookmarkButton" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fbookmark%2Fp%2Fa950e6f9eb72&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;source=---footer_actions--a950e6f9eb72---------------------bookmark_footer-----------" rel="noopener follow"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" fill="none" viewBox="0 0 25 25" class="du lw" aria-label="Add to list bookmark button"><path fill="currentColor" d="M18 2.5a.5.5 0 0 1 1 0V5h2.5a.5.5 0 0 1 0 1H19v2.5a.5.5 0 1 1-1 0V6h-2.5a.5.5 0 0 1 0-1H18zM7 7a1 1 0 0 1 1-1h3.5a.5.5 0 0 0 0-1H8a2 2 0 0 0-2 2v14a.5.5 0 0 0 .805.396L12.5 17l5.695 4.396A.5.5 0 0 0 19 21v-8.5a.5.5 0 0 0-1 0v7.485l-5.195-4.012a.5.5 0 0 0-.61 0L7 19.985z"></path></svg></a></span></div></div></div><div class="sj l ix"><div class="bm" aria-hidden="false" aria-describedby="postFooterSocialMenu" aria-labelledby="postFooterSocialMenu"><div><div class="bm" aria-hidden="false"><button aria-controls="postFooterSocialMenu" aria-expanded="false" aria-label="Share Post" data-testid="footerSocialShareButton" class="af fk ah ai aj ak al me an ao ap ex mf mg lt mh"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.218 4.931a.4.4 0 0 1-.118.132l.012.006a.45.45 0 0 1-.292.074.5.5 0 0 1-.3-.13l-2.02-2.02v7.07c0 .28-.23.5-.5.5s-.5-.22-.5-.5v-7.04l-2 2a.45.45 0 0 1-.57.04h-.02a.4.4 0 0 1-.16-.3.4.4 0 0 1 .1-.32l2.8-2.8a.5.5 0 0 1 .7 0l2.8 2.79a.42.42 0 0 1 .068.498m-.106.138.008.004v-.01zM16 7.063h1.5a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-11c-1.1 0-2-.9-2-2v-10a2 2 0 0 1 2-2H8a.5.5 0 0 1 .35.15.5.5 0 0 1 .15.35.5.5 0 0 1-.15.35.5.5 0 0 1-.35.15H6.4c-.5 0-.9.4-.9.9v10.2a.9.9 0 0 0 .9.9h11.2c.5 0 .9-.4.9-.9v-10.2c0-.5-.4-.9-.9-.9H16a.5.5 0 0 1 0-1" clip-rule="evenodd"></path></svg></button></div></div></div></div></div></div></div></div></div></footer><div class="sk sl sm sn so l"><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="sp bh r sq"></div><div class="sr l"><div class="ab ss st su iz iy"><div class="sv sw sx sy sz ta tb tc td te ab cp"><div class="h k"><a href="https://proandroiddev.com/?source=post_page---post_publication_info--a950e6f9eb72--------------------------------" rel="noopener follow"><div class="fj ab"><img alt="ProAndroidDev" class="tf ib ic cx" src="https://miro.medium.com/v2/resize:fill:96:96/1*XVtdl45m8YaYrPI4buJ5yQ.png" width="48" height="48" loading="lazy"/><div class="tf l ic ib fs n fr tg"></div></div></a></div><div class="j i d"><a href="https://proandroiddev.com/?source=post_page---post_publication_info--a950e6f9eb72--------------------------------" rel="noopener follow"><div class="fj ab"><img alt="ProAndroidDev" class="tf ti th cx" src="https://miro.medium.com/v2/resize:fill:128:128/1*XVtdl45m8YaYrPI4buJ5yQ.png" width="64" height="64" loading="lazy"/><div class="tf l th ti fs n fr tg"></div></div></a></div><div class="j i d tj ix"><div class="ab"><span><a class="bf b bg z tk rr tl tm tn to tp ev ew tq tr ts fa fb fc fd bm fe ff" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fcollection%2Fproandroiddev&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;collection=ProAndroidDev&amp;collectionId=c72404660798&amp;source=post_page---post_publication_info--a950e6f9eb72---------------------follow_profile-----------" rel="noopener follow">Follow</a></span></div></div></div><div class="ab co tt"><div class="tu tv tw tx ty l"><a class="af ag ah aj ak al am an ao ap aq ar as at ab q" href="https://proandroiddev.com/?source=post_page---post_publication_info--a950e6f9eb72--------------------------------" rel="noopener follow"><h2 class="pw-author-name bf ua ub uc ud ue uf ug nv qz ra nz rc rd od rf rg bk"><span class="gn tz">Published in <!-- -->ProAndroidDev</span></h2></a><div class="rp ab ia"><div class="l ix"><span class="pw-follower-count bf b bg z du"><a class="af ag ah ai aj ak al am an ao ap aq ar iq" rel="noopener follow" href="/followers?source=post_page---post_publication_info--a950e6f9eb72--------------------------------">62K Followers</a></span></div><div class="bf b bg z du ab jd"><span class="ir l" aria-hidden="true"><span class="bf b bg z du">·</span></span><a class="af ag ah ai aj ak al am an ao ap aq ar iq" rel="noopener follow" href="/benchmarking-koin-vs-dagger-hilt-in-modern-android-development-2024-ff7bb40470df?source=post_page---post_publication_info--a950e6f9eb72--------------------------------">Last published <!-- -->15 hours ago</a></div></div><div class="uh l"><p class="bf b bg z bk"><span class="gn">The latest posts from Android Professionals and Google Developer Experts.</span></p></div></div></div><div class="h k"><div class="ab"><span><a class="bf b bg z tk rr tl tm tn to tp ev ew tq tr ts fa fb fc fd bm fe ff" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fcollection%2Fproandroiddev&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;collection=ProAndroidDev&amp;collectionId=c72404660798&amp;source=post_page---post_publication_info--a950e6f9eb72---------------------follow_profile-----------" rel="noopener follow">Follow</a></span></div></div></div></div><div class="ab ss st su iz iy"><div class="sv sw sx sy sz ta tb tc td te ab cp"><div class="h k"><a tabindex="0" href="https://medium.com/@siddh.gupta99?source=post_page---post_author_info--a950e6f9eb72--------------------------------" rel="noopener follow"><div class="l fj"><img alt="Siddharth Gupta" class="l fd by ic ib cx" src="https://miro.medium.com/v2/resize:fill:96:96/1*6rI29yuZZDr-3XD0qlJ-RQ.jpeg" width="48" height="48" loading="lazy"/><div class="fr by l ic ib fs n ay tg"></div></div></a></div><div class="j i d"><a tabindex="0" href="https://medium.com/@siddh.gupta99?source=post_page---post_author_info--a950e6f9eb72--------------------------------" rel="noopener follow"><div class="l fj"><img alt="Siddharth Gupta" class="l fd by th ti cx" src="https://miro.medium.com/v2/resize:fill:128:128/1*6rI29yuZZDr-3XD0qlJ-RQ.jpeg" width="64" height="64" loading="lazy"/><div class="fr by l th ti fs n ay tg"></div></div></a></div><div class="j i d tj ix"><div class="ab"><span><a class="bf b bg z tk rr tl tm tn to tp ev ew tq tr ts fa fb fc fd bm fe ff" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fuser%2Fe072cea221fc&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=post_page-e072cea221fc--post_author_info--a950e6f9eb72---------------------follow_profile-----------" rel="noopener follow">Follow</a></span></div></div></div><div class="ab co tt"><div class="tu tv tw tx ty l"><a class="af ag ah aj ak al am an ao ap aq ar as at ab q" href="https://medium.com/@siddh.gupta99?source=post_page---post_author_info--a950e6f9eb72--------------------------------" rel="noopener follow"><h2 class="pw-author-name bf ua ub uc ud ue uf ug nv qz ra nz rc rd od rf rg bk"><span class="gn tz">Written by <!-- -->Siddharth Gupta</span></h2></a><div class="rp ab ia"><div class="l ix"><span class="pw-follower-count bf b bg z du"><a class="af ag ah ai aj ak al am an ao ap aq ar iq" href="https://medium.com/@siddh.gupta99/followers?source=post_page---post_author_info--a950e6f9eb72--------------------------------" rel="noopener follow">8 Followers</a></span></div><div class="bf b bg z du ab jd"><span class="ir l" aria-hidden="true"><span class="bf b bg z du">·</span></span><a class="af ag ah ai aj ak al am an ao ap aq ar iq" href="https://medium.com/@siddh.gupta99/following?source=post_page---post_author_info--a950e6f9eb72--------------------------------" rel="noopener follow">6 Following</a></div></div><div class="uh l"><p class="bf b bg z bk"><span class="gn">Mobile Developer building CRED</span></p></div></div></div><div class="h k"><div class="ab"><span><a class="bf b bg z tk rr tl tm tn to tp ev ew tq tr ts fa fb fc fd bm fe ff" href="https://medium.com/m/signin?actionUrl=https%3A%2F%2Fmedium.com%2F_%2Fsubscribe%2Fuser%2Fe072cea221fc&amp;operation=register&amp;redirect=https%3A%2F%2Fproandroiddev.com%2Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72&amp;user=Siddharth+Gupta&amp;userId=e072cea221fc&amp;source=post_page-e072cea221fc--post_author_info--a950e6f9eb72---------------------follow_profile-----------" rel="noopener follow">Follow</a></span></div></div></div></div></div></div><div class="ui l"><div class="sp bh r uj uk ul um un"></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="ab q cp"><h2 class="bf ua ol on oo op or os ot ov ow ox oz pa pb pd pe bk">No responses yet</h2><div class="ab uo"><div><div class="bm" aria-hidden="false"><a class="up uq" href="https://policy.medium.com/medium-rules-30e5502c4eb4?source=post_page---post_responses--a950e6f9eb72--------------------------------" rel="noopener follow" target="_blank"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25"><path fill-rule="evenodd" d="M11.987 5.036a.754.754 0 0 1 .914-.01c.972.721 1.767 1.218 2.6 1.543.828.322 1.719.485 2.887.505a.755.755 0 0 1 .741.757c-.018 3.623-.43 6.256-1.449 8.21-1.034 1.984-2.662 3.209-4.966 4.083a.75.75 0 0 1-.537-.003c-2.243-.874-3.858-2.095-4.897-4.074-1.024-1.951-1.457-4.583-1.476-8.216a.755.755 0 0 1 .741-.757c1.195-.02 2.1-.182 2.923-.503.827-.322 1.6-.815 2.519-1.535m.468.903c-.897.69-1.717 1.21-2.623 1.564-.898.35-1.856.527-3.026.565.037 3.45.469 5.817 1.36 7.515.884 1.684 2.25 2.762 4.284 3.571 2.092-.81 3.465-1.89 4.344-3.575.886-1.698 1.299-4.065 1.334-7.512-1.149-.039-2.091-.217-2.99-.567-.906-.353-1.745-.873-2.683-1.561m-.009 9.155a2.672 2.672 0 1 0 0-5.344 2.672 2.672 0 0 0 0 5.344m0 1a3.672 3.672 0 1 0 0-7.344 3.672 3.672 0 0 0 0 7.344m-1.813-3.777.525-.526.916.917 1.623-1.625.526.526-2.149 2.152z" clip-rule="evenodd"></path></svg></a></div></div></div></div></div></div></div><div class="ur us ut uu uv l bx"><div class="h k j"><div class="sp bh uw ux"></div><div class="ab cb"><div class="ci bh fz ga gb gc"><div class="uy ab kv ja"><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://help.medium.com/hc/en-us?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Help</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://medium.statuspage.io/?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Status</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://medium.com/about?autoplay=1&amp;source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">About</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://medium.com/jobs-at-medium/work-at-medium-959d1a85284e?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Careers</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="pressinquiries@medium.com?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Press</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://blog.medium.com/?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Blog</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://policy.medium.com/medium-privacy-policy-f03bf92035c9?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Privacy</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://policy.medium.com/medium-terms-of-service-9db0094a1e0f?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Terms</p></a></div><div class="uz va l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://speechify.com/medium?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Text to speech</p></a></div><div class="uz l"><a class="af ag ah ai aj ak al am an ao ap aq ar as at" href="https://medium.com/business?source=post_page-----a950e6f9eb72--------------------------------" rel="noopener follow"><p class="bf b dv z du">Teams</p></a></div></div></div></div></div></div></div></div></div></div><script>window.__BUILD_ID__="main-20241126-181518-0cb59a020f"</script><script>window.__GRAPHQL_URI__ = "https://proandroiddev.com/_/graphql"</script><script>window.__PRELOADED_STATE__ = {"algolia":{"queries":{}},"cache":{"experimentGroupSet":true,"reason":"This request is not using the cache middleware worker","group":"disabled","tags":["group-edgeCachePosts","post-a950e6f9eb72","user-e072cea221fc","collection-c72404660798"],"serverVariantState":"","middlewareEnabled":false,"cacheStatus":"DYNAMIC","shouldUseCache":false,"vary":[],"lohpSummerUpsellEnabled":false,"publicationHierarchyEnabledWeb":false,"postBottomResponsesEnabled":false},"client":{"hydrated":false,"isUs":false,"isNativeMedium":false,"isSafariMobile":false,"isSafari":false,"isFirefox":false,"routingEntity":{"type":"COLLECTION","id":"c72404660798","explicit":true},"viewerIsBot":false},"debug":{"requestId":"e56412a2-1809-435b-a09e-c87767ae081b","hybridDevServices":[],"originalSpanCarrier":{"traceparent":"00-61a049e172d45b0f76710e31e6fae811-6a9e66dc917bd10e-01"}},"multiVote":{"clapsPerPost":{}},"navigation":{"branch":{"show":null,"hasRendered":null,"blockedByCTA":false},"hideGoogleOneTap":false,"hasRenderedAlternateUserBanner":null,"currentLocation":"https:\u002F\u002Fproandroiddev.com\u002Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72","host":"proandroiddev.com","hostname":"proandroiddev.com","referrer":"","hasSetReferrer":false,"susiModal":{"step":null,"operation":"register"},"postRead":false,"partnerProgram":{"selectedCountryCode":null},"queryString":"?source=collection_home---4------4-----------------------"},"config":{"nodeEnv":"production","version":"main-20241126-181518-0cb59a020f","target":"production","productName":"Medium","publicUrl":"https:\u002F\u002Fcdn-client.medium.com\u002Flite","authDomain":"medium.com","authGoogleClientId":"216296035834-k1k6qe060s2tp2a2jam4ljdcms00sttg.apps.googleusercontent.com","favicon":"production","glyphUrl":"https:\u002F\u002Fglyph.medium.com","branchKey":"key_live_ofxXr2qTrrU9NqURK8ZwEhknBxiI6KBm","algolia":{"appId":"MQ57UUUQZ2","apiKeySearch":"394474ced050e3911ae2249ecc774921","indexPrefix":"medium_","host":"-dsn.algolia.net"},"recaptchaKey":"6Lfc37IUAAAAAKGGtC6rLS13R1Hrw_BqADfS1LRk","recaptcha3Key":"6Lf8R9wUAAAAABMI_85Wb8melS7Zj6ziuf99Yot5","recaptchaEnterpriseKeyId":"6Le-uGgpAAAAAPprRaokM8AKthQ9KNGdoxaGUvVp","datadog":{"applicationId":"6702d87d-a7e0-42fe-bbcb-95b469547ea0","clientToken":"pub853ea8d17ad6821d9f8f11861d23dfed","rumToken":"pubf9cc52896502b9413b68ba36fc0c7162","context":{"deployment":{"target":"production","tag":"main-20241126-181518-0cb59a020f","commit":"0cb59a020f4453d0900f671f1a6576feecc55e74"}},"datacenter":"us"},"googleAnalyticsCode":"G-7JY7T788PK","googlePay":{"apiVersion":"2","apiVersionMinor":"0","merchantId":"BCR2DN6TV7EMTGBM","merchantName":"Medium","instanceMerchantId":"13685562959212738550"},"applePay":{"version":3},"signInWallCustomDomainCollectionIds":["3a8144eabfe3","336d898217ee","61061eb0c96b","138adf9c44c","819cc2aaeee0"],"mediumMastodonDomainName":"me.dm","mediumOwnedAndOperatedCollectionIds":["8a9336e5bb4","b7e45b22fec3","193b68bd4fba","8d6b8a439e32","54c98c43354d","3f6ecf56618","d944778ce714","92d2092dc598","ae2a65f35510","1285ba81cada","544c7006046e","fc8964313712","40187e704f1c","88d9857e584e","7b6769f2748b","bcc38c8f6edf","cef6983b292","cb8577c9149e","444d13b52878","713d7dbc99b0","ef8e90590e66","191186aaafa0","55760f21cdc5","9dc80918cc93","bdc4052bbdba","8ccfed20cbb2"],"tierOneDomains":["medium.com","thebolditalic.com","arcdigital.media","towardsdatascience.com","uxdesign.cc","codeburst.io","psiloveyou.xyz","writingcooperative.com","entrepreneurshandbook.co","prototypr.io","betterhumans.coach.me","theascent.pub"],"topicsToFollow":["d61cf867d93f","8a146bc21b28","1eca0103fff3","4d562ee63426","aef1078a3ef5","e15e46793f8d","6158eb913466","55f1c20aba7a","3d18b94f6858","4861fee224fd","63c6f1f93ee","1d98b3a9a871","decb52b64abf","ae5d4995e225","830cded25262"],"topicToTagMappings":{"accessibility":"accessibility","addiction":"addiction","android-development":"android-development","art":"art","artificial-intelligence":"artificial-intelligence","astrology":"astrology","basic-income":"basic-income","beauty":"beauty","biotech":"biotech","blockchain":"blockchain","books":"books","business":"business","cannabis":"cannabis","cities":"cities","climate-change":"climate-change","comics":"comics","coronavirus":"coronavirus","creativity":"creativity","cryptocurrency":"cryptocurrency","culture":"culture","cybersecurity":"cybersecurity","data-science":"data-science","design":"design","digital-life":"digital-life","disability":"disability","economy":"economy","education":"education","equality":"equality","family":"family","feminism":"feminism","fiction":"fiction","film":"film","fitness":"fitness","food":"food","freelancing":"freelancing","future":"future","gadgets":"gadgets","gaming":"gaming","gun-control":"gun-control","health":"health","history":"history","humor":"humor","immigration":"immigration","ios-development":"ios-development","javascript":"javascript","justice":"justice","language":"language","leadership":"leadership","lgbtqia":"lgbtqia","lifestyle":"lifestyle","machine-learning":"machine-learning","makers":"makers","marketing":"marketing","math":"math","media":"media","mental-health":"mental-health","mindfulness":"mindfulness","money":"money","music":"music","neuroscience":"neuroscience","nonfiction":"nonfiction","outdoors":"outdoors","parenting":"parenting","pets":"pets","philosophy":"philosophy","photography":"photography","podcasts":"podcast","poetry":"poetry","politics":"politics","privacy":"privacy","product-management":"product-management","productivity":"productivity","programming":"programming","psychedelics":"psychedelics","psychology":"psychology","race":"race","relationships":"relationships","religion":"religion","remote-work":"remote-work","san-francisco":"san-francisco","science":"science","self":"self","self-driving-cars":"self-driving-cars","sexuality":"sexuality","social-media":"social-media","society":"society","software-engineering":"software-engineering","space":"space","spirituality":"spirituality","sports":"sports","startups":"startup","style":"style","technology":"technology","transportation":"transportation","travel":"travel","true-crime":"true-crime","tv":"tv","ux":"ux","venture-capital":"venture-capital","visual-design":"visual-design","work":"work","world":"world","writing":"writing"},"defaultImages":{"avatar":{"imageId":"1*dmbNkD5D-u45r44go_cf0g.png","height":150,"width":150},"orgLogo":{"imageId":"7*V1_7XP4snlmqrc_0Njontw.png","height":110,"width":500},"postLogo":{"imageId":"bd978bb536350a710e8efb012513429cabdc4c28700604261aeda246d0f980b7","height":810,"width":1440},"postPreviewImage":{"imageId":"1*hn4v1tCaJy7cWMyb0bpNpQ.png","height":386,"width":579}},"collectionStructuredData":{"8d6b8a439e32":{"name":"Elemental","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F980\u002F1*9ygdqoKprhwuTVKUM0DLPA@2x.png","width":980,"height":159}}},"3f6ecf56618":{"name":"Forge","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F596\u002F1*uULpIlImcO5TDuBZ6lm7Lg@2x.png","width":596,"height":183}}},"ae2a65f35510":{"name":"GEN","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F264\u002F1*RdVZMdvfV3YiZTw6mX7yWA.png","width":264,"height":140}}},"88d9857e584e":{"name":"LEVEL","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*JqYMhNX6KNNb2UlqGqO2WQ.png","width":540,"height":108}}},"7b6769f2748b":{"name":"Marker","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fcdn-images-1.medium.com\u002Fmax\u002F383\u002F1*haCUs0wF6TgOOvfoY-jEoQ@2x.png","width":383,"height":92}}},"444d13b52878":{"name":"OneZero","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*cw32fIqCbRWzwJaoQw6BUg.png","width":540,"height":123}}},"8ccfed20cbb2":{"name":"Zora","data":{"@type":"NewsMediaOrganization","ethicsPolicy":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Farticles\u002F360043290473","logo":{"@type":"ImageObject","url":"https:\u002F\u002Fmiro.medium.com\u002Fmax\u002F540\u002F1*tZUQqRcCCZDXjjiZ4bDvgQ.png","width":540,"height":106}}}},"embeddedPostIds":{"coronavirus":"cd3010f9d81f"},"sharedCdcMessaging":{"COVID_APPLICABLE_TAG_SLUGS":[],"COVID_APPLICABLE_TOPIC_NAMES":[],"COVID_APPLICABLE_TOPIC_NAMES_FOR_TOPIC_PAGE":[],"COVID_MESSAGES":{"tierA":{"text":"For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":66,"end":73,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"tierB":{"text":"Anyone can publish on Medium per our Policies, but we don’t fact-check every story. For more info about the coronavirus, see cdc.gov.","markups":[{"start":37,"end":45,"href":"https:\u002F\u002Fhelp.medium.com\u002Fhc\u002Fen-us\u002Fcategories\u002F201931128-Policies-Safety"},{"start":125,"end":132,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"paywall":{"text":"This article has been made free for everyone, thanks to Medium Members. For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":56,"end":70,"href":"https:\u002F\u002Fmedium.com\u002Fmembership"},{"start":138,"end":145,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]},"unbound":{"text":"This article is free for everyone, thanks to Medium Members. For more information on the novel coronavirus and Covid-19, visit cdc.gov.","markups":[{"start":45,"end":59,"href":"https:\u002F\u002Fmedium.com\u002Fmembership"},{"start":127,"end":134,"href":"https:\u002F\u002Fwww.cdc.gov\u002Fcoronavirus\u002F2019-nCoV"}]}},"COVID_BANNER_POST_ID_OVERRIDE_WHITELIST":["3b31a67bff4a"]},"sharedVoteMessaging":{"TAGS":["politics","election-2020","government","us-politics","election","2020-presidential-race","trump","donald-trump","democrats","republicans","congress","republican-party","democratic-party","biden","joe-biden","maga"],"TOPICS":["politics","election"],"MESSAGE":{"text":"Find out more about the U.S. election results here.","markups":[{"start":46,"end":50,"href":"https:\u002F\u002Fcookpolitical.com\u002F2020-national-popular-vote-tracker"}]},"EXCLUDE_POSTS":["397ef29e3ca5"]},"embedPostRules":[],"recircOptions":{"v1":{"limit":3},"v2":{"limit":8}},"braintreeClientKey":"production_zjkj96jm_m56f8fqpf7ngnrd4","braintree":{"enabled":true,"merchantId":"m56f8fqpf7ngnrd4","merchantAccountId":{"usd":"AMediumCorporation_instant","eur":"amediumcorporation_EUR","cad":"amediumcorporation_CAD"},"publicKey":"ds2nn34bg2z7j5gd","braintreeEnvironment":"production","dashboardUrl":"https:\u002F\u002Fwww.braintreegateway.com\u002Fmerchants","gracePeriodDurationInDays":14,"mediumMembershipPlanId":{"monthly":"ce105f8c57a3","monthlyV2":"e8a5e126-792b-4ee6-8fba-d574c1b02fc5","monthlyWithTrial":"d5ee3dbe3db8","monthlyPremium":"fa741a9b47a2","yearly":"a40ad4a43185","yearlyV2":"3815d7d6-b8ca-4224-9b8c-182f9047866e","yearlyStaff":"d74fb811198a","yearlyWithTrial":"b3bc7350e5c7","yearlyPremium":"e21bd2c12166","monthlyOneYearFree":"e6c0637a-2bad-4171-ab4f-3c268633d83c","monthly25PercentOffFirstYear":"235ecc62-0cdb-49ae-9378-726cd21c504b","monthly20PercentOffFirstYear":"ba518864-9c13-4a99-91ca-411bf0cac756","monthly15PercentOffFirstYear":"594c029b-9f89-43d5-88f8-8173af4e070e","monthly10PercentOffFirstYear":"c6c7bc9a-40f2-4b51-8126-e28511d5bdb0","monthlyForStudents":"629ebe51-da7d-41fd-8293-34cd2f2030a8","yearlyOneYearFree":"78ba7be9-0d9f-4ece-aa3e-b54b826f2bf1","yearly25PercentOffFirstYear":"2dbb010d-bb8f-4eeb-ad5c-a08509f42d34","yearly20PercentOffFirstYear":"47565488-435b-47f8-bf93-40d5fbe0ebc8","yearly15PercentOffFirstYear":"8259809b-0881-47d9-acf7-6c001c7f720f","yearly10PercentOffFirstYear":"9dd694fb-96e1-472c-8d9e-3c868d5c1506","yearlyForStudents":"e29345ef-ab1c-4234-95c5-70e50fe6bc23","monthlyCad":"p52orjkaceei","yearlyCad":"h4q9g2up9ktt"},"braintreeDiscountId":{"oneMonthFree":"MONTHS_FREE_01","threeMonthsFree":"MONTHS_FREE_03","sixMonthsFree":"MONTHS_FREE_06","fiftyPercentOffOneYear":"FIFTY_PERCENT_OFF_ONE_YEAR"},"3DSecureVersion":"2","defaultCurrency":"usd","providerPlanIdCurrency":{"4ycw":"usd","rz3b":"usd","3kqm":"usd","jzw6":"usd","c2q2":"usd","nnsw":"usd","q8qw":"usd","d9y6":"usd","fx7w":"cad","nwf2":"cad"}},"paypalClientId":"AXj1G4fotC2GE8KzWX9mSxCH1wmPE3nJglf4Z2ig_amnhvlMVX87otaq58niAg9iuLktVNF_1WCMnN7v","paypal":{"host":"https:\u002F\u002Fapi.paypal.com:443","clientMode":"production","serverMode":"live","webhookId":"4G466076A0294510S","monthlyPlan":{"planId":"P-9WR0658853113943TMU5FDQA","name":"Medium Membership (Monthly) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"yearlyPlan":{"planId":"P-7N8963881P8875835MU5JOPQ","name":"Medium Membership (Annual) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"oneYearGift":{"name":"Medium Membership (1 Year, Digital Gift Code)","description":"Unlimited access to the best and brightest stories on Medium. Gift codes can be redeemed at medium.com\u002Fredeem.","price":"50.00","currency":"USD","sku":"membership-gift-1-yr"},"oldMonthlyPlan":{"planId":"P-96U02458LM656772MJZUVH2Y","name":"Medium Membership (Monthly)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"oldYearlyPlan":{"planId":"P-59P80963JF186412JJZU3SMI","name":"Medium Membership (Annual)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"monthlyPlanWithTrial":{"planId":"P-66C21969LR178604GJPVKUKY","name":"Medium Membership (Monthly) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"yearlyPlanWithTrial":{"planId":"P-6XW32684EX226940VKCT2MFA","name":"Medium Membership (Annual) with setup fee","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"oldMonthlyPlanNoSetupFee":{"planId":"P-4N046520HR188054PCJC7LJI","name":"Medium Membership (Monthly)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed monthly."},"oldYearlyPlanNoSetupFee":{"planId":"P-7A4913502Y5181304CJEJMXQ","name":"Medium Membership (Annual)","description":"Unlimited access to the best and brightest stories on Medium. Membership billed annually."},"sdkUrl":"https:\u002F\u002Fwww.paypal.com\u002Fsdk\u002Fjs"},"stripePublishableKey":"pk_live_7FReX44VnNIInZwrIIx6ghjl","log":{"json":true,"level":"info"},"imageUploadMaxSizeMb":25,"staffPicks":{"title":"Staff Picks","catalogId":"c7bc6e1ee00f"}},"session":{"xsrf":""}}</script><script>window.__APOLLO_STATE__ = {"ROOT_QUERY":{"__typename":"Query","viewer":null,"variantFlags":[{"__typename":"VariantFlag","name":"android_enable_image_sharer","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lite_server_upstream_deadlines","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_group_gifting","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_google_pay","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_iceland_forced_android","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_display_paywall_after_onboarding","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_iceland_nux","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"num_post_bottom_responses_to_show","valueType":{"__typename":"VariantFlagString","value":"3"}},{"__typename":"VariantFlag","name":"enable_android_dynamic_programming_paywall","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_apple_webhook","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"browsable_stream_config_bucket","valueType":{"__typename":"VariantFlagString","value":"curated-topics"}},{"__typename":"VariantFlag","name":"signin_services","valueType":{"__typename":"VariantFlagString","value":"twitter,facebook,google,email,google-fastidv,google-one-tap,apple"}},{"__typename":"VariantFlag","name":"enable_updated_pub_recs_ui","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_moc_load_processor_first_story","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_tag_recs","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_topic_portals","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_entities_to_follow_v2","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_maim_the_meter","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_pill_based_home_feed","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_integration","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_premium_tier_badge","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_seamless_social_sharing","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"available_monthly_premium_plan","valueType":{"__typename":"VariantFlagString","value":"12a660186432"}},{"__typename":"VariantFlag","name":"enable_author_cards","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_deprecate_legacy_providers_v3","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_boost_nia_v01","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_trial_membership","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_configure_pronouns","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_explicit_signals_updated_post_previews","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_publication_hierarchy_web","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_social_share_sheet","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_friend_links_postpage_banners","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_creator_welcome_email","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"onboarding_tags_from_top_views","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_post_bottom_responses","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_rex_aggregator_v2","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_speechify_widget","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_friend_links_creation","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_import","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_recirc_model","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_newsletter_lo_flow_custom_domains","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_recaptcha_enterprise","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_rating_prompt_stories_read_threshold","valueType":{"__typename":"VariantFlagNumber","value":2}},{"__typename":"VariantFlag","name":"enable_ios_dynamic_paywall_programming","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_legacy_feed_in_iceland","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_conversion_ranker_v2","valueType":{"__typename":"VariantFlagString","value":"control"}},{"__typename":"VariantFlag","name":"enable_footer_app_buttons","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ios_easy_resubscribe","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lite_homepage","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_switch_plan_premium_tier","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"available_annual_premium_plan","valueType":{"__typename":"VariantFlagString","value":"4a442ace1476"}},{"__typename":"VariantFlag","name":"can_send_tips_v0","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lo_homepage","valueType":{"__typename":"VariantFlagString","value":"control"}},{"__typename":"VariantFlag","name":"enable_starspace","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"price_smoke_test_monthly","valueType":{"__typename":"VariantFlagString","value":""}},{"__typename":"VariantFlag","name":"enable_automod","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"limit_post_referrers","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ios_offline_reading","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_app_flirty_thirty","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_marketing_emails","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_android_verified_author","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_google_webhook","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_cache_less_following_feed","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_update_topic_portals_wtf","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_lists_v2","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_tipping_v0_android","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"skip_fs_cache_user_vals","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_android_offline_reading","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_medium2_kbfd","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_moc_load_processor_all_recs_surfaces","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_see_pronouns","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_sprig","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_enable_friend_links_creation","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"mobile_custom_app_icon","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_simplified_digest_v2_b","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_susi_redesign_android","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_tipping_v0_ios","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"available_monthly_plan","valueType":{"__typename":"VariantFlagString","value":"60e220181034"}},{"__typename":"VariantFlag","name":"enable_android_miro_v2","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_post_bottom_responses_input","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_susi_redesign_ios","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_bayesian_average_pub_search","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_bg_post_post","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_pp_v4","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_apple_sign_in","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_paypal","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"reader_fair_distribution_non_qp","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"allow_test_auth","valueType":{"__typename":"VariantFlagString","value":"disallow"}},{"__typename":"VariantFlag","name":"available_annual_plan","valueType":{"__typename":"VariantFlagString","value":"2c754bcc2995"}},{"__typename":"VariantFlag","name":"price_smoke_test_yearly","valueType":{"__typename":"VariantFlagString","value":""}},{"__typename":"VariantFlag","name":"allow_signup","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_client","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_intrinsic_automatic_actions","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lite_archive_page","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_new_stripe_customers","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"allow_access","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_recommended_publishers_query","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_remove_twitter_onboarding_step","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_auto_follow_on_subscribe","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ranker_v10","valueType":{"__typename":"VariantFlagString","value":"control"}},{"__typename":"VariantFlag","name":"ios_enable_verified_book_author","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_aurora_pub_follower_page","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_author_cards_byline","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_mastodon_avatar_upload","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"reengagement_notification_duration","valueType":{"__typename":"VariantFlagNumber","value":3}},{"__typename":"VariantFlag","name":"enable_eventstats_event_processing","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_android_dynamic_aspirational_paywall","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_billing_frequency_on_step2","valueType":{"__typename":"VariantFlagString","value":"control"}},{"__typename":"VariantFlag","name":"enable_pp_country_expansion","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_update_explore_wtf","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_mastodon_for_members_username_selection","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_tribute_landing_page","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_enable_home_post_menu","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ml_rank_rex_anno","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_pre_pp_v4","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_premium_tier","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"coronavirus_topic_recirc","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ios_autorefresh","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"limit_user_follows","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"redefined_top_posts","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_syntax_highlight","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"signup_services","valueType":{"__typename":"VariantFlagString","value":"twitter,facebook,google,email,google-fastidv,google-one-tap,apple"}},{"__typename":"VariantFlag","name":"enable_tick_landing_page","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_google_one_tap","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_sharer_validate_post_share_key","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_enable_editor_new_publishing_flow","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_webhook","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_enable_lock_responses","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_braintree_apple_pay","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_diversification_rex","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"rex_generator_max_candidates","valueType":{"__typename":"VariantFlagNumber","value":1000}},{"__typename":"VariantFlag","name":"enable_explicit_signals","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_rex_new_push_notification_endpoint","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lite_response_markup","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"textshots_userid","valueType":{"__typename":"VariantFlagString","value":""}},{"__typename":"VariantFlag","name":"enable_new_manage_membership_flow","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_verifications_service","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_enable_friend_links_postpage_banners","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_conversion_model_v2","valueType":{"__typename":"VariantFlagString","value":"group_2"}},{"__typename":"VariantFlag","name":"enable_moc_load_processor_c","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"glyph_font_set","valueType":{"__typename":"VariantFlagString","value":"m2-unbound-source-serif-pro"}},{"__typename":"VariantFlag","name":"goliath_externalsearch_enable_comment_deindexation","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"can_receive_tips_v0","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_sharer_create_post_share_key","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_branch_io","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_rex_reading_history","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"ios_in_app_free_trial","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_rito_upstream_deadlines","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"disable_partner_program_enrollment","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_lite_continue_this_thread","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_mastodon_for_members","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_ios_dynamic_paywall_aspiriational","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_members_only_audio","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_speechify_ios","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"android_two_hour_refresh","valueType":{"__typename":"VariantFlagBoolean","value":true}},{"__typename":"VariantFlag","name":"enable_abandoned_cart_promotion_email","valueType":{"__typename":"VariantFlagBoolean","value":true}}],"collectionByDomainOrSlug({\"domainOrSlug\":\"proandroiddev.com\"})":{"__ref":"Collection:c72404660798"},"postResult({\"id\":\"a950e6f9eb72\"})":{"__ref":"Post:a950e6f9eb72"}},"ImageMetadata:1*A8VytPZQhvUf_MG6hm_Dlw.png":{"__typename":"ImageMetadata","id":"1*A8VytPZQhvUf_MG6hm_Dlw.png"},"Collection:c72404660798":{"__typename":"Collection","id":"c72404660798","favicon":{"__ref":"ImageMetadata:1*A8VytPZQhvUf_MG6hm_Dlw.png"},"customStyleSheet":null,"colorPalette":{"__typename":"ColorPalette","highlightSpectrum":{"__typename":"ColorSpectrum","backgroundColor":"#FFFFFFFF","colorPoints":[{"__typename":"ColorPoint","color":"#FFE4F8EF","point":0},{"__typename":"ColorPoint","color":"#FFDEF8ED","point":0.1},{"__typename":"ColorPoint","color":"#FFD9F7EB","point":0.2},{"__typename":"ColorPoint","color":"#FFD3F6E9","point":0.3},{"__typename":"ColorPoint","color":"#FFCEF6E7","point":0.4},{"__typename":"ColorPoint","color":"#FFC8F5E4","point":0.5},{"__typename":"ColorPoint","color":"#FFC2F4E2","point":0.6},{"__typename":"ColorPoint","color":"#FFBCF4E0","point":0.7},{"__typename":"ColorPoint","color":"#FFB5F3DE","point":0.8},{"__typename":"ColorPoint","color":"#FFAFF2DB","point":0.9},{"__typename":"ColorPoint","color":"#FFA8F2D9","point":1}]},"defaultBackgroundSpectrum":{"__typename":"ColorSpectrum","backgroundColor":"#FFFFFFFF","colorPoints":[{"__typename":"ColorPoint","color":"#FF2E987E","point":0},{"__typename":"ColorPoint","color":"#FF318D75","point":0.1},{"__typename":"ColorPoint","color":"#FF32826C","point":0.2},{"__typename":"ColorPoint","color":"#FF327663","point":0.3},{"__typename":"ColorPoint","color":"#FF306B5A","point":0.4},{"__typename":"ColorPoint","color":"#FF2E5F50","point":0.5},{"__typename":"ColorPoint","color":"#FF2A5347","point":0.6},{"__typename":"ColorPoint","color":"#FF26463C","point":0.7},{"__typename":"ColorPoint","color":"#FF203931","point":0.8},{"__typename":"ColorPoint","color":"#FF192C25","point":0.9},{"__typename":"ColorPoint","color":"#FF101D19","point":1}]},"tintBackgroundSpectrum":{"__typename":"ColorSpectrum","backgroundColor":"#FF7DE1C3","colorPoints":[{"__typename":"ColorPoint","color":"#FF7DE1C3","point":0},{"__typename":"ColorPoint","color":"#FF6ED2B5","point":0.1},{"__typename":"ColorPoint","color":"#FF5EC3A6","point":0.2},{"__typename":"ColorPoint","color":"#FF4EB397","point":0.3},{"__typename":"ColorPoint","color":"#FF3CA388","point":0.4},{"__typename":"ColorPoint","color":"#FF269278","point":0.5},{"__typename":"ColorPoint","color":"#FF008168","point":0.6},{"__typename":"ColorPoint","color":"#FF006F57","point":0.7},{"__typename":"ColorPoint","color":"#FF005C45","point":0.8},{"__typename":"ColorPoint","color":"#FF004732","point":0.9},{"__typename":"ColorPoint","color":"#FF002F1C","point":1}]}},"domain":"proandroiddev.com","slug":"proandroiddev","googleAnalyticsId":null,"editors":[{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:fbb92b85b19e"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:eac743c05401"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:c6e8e225f7d5"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:96912518b8bb"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:d022c4e0f12b"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:6fffa5371f97"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:bf87f3641b6c"}},{"__typename":"CollectionMastheadUserItem","user":{"__ref":"User:f6e9347ca668"}}],"name":"ProAndroidDev","avatar":{"__ref":"ImageMetadata:1*XVtdl45m8YaYrPI4buJ5yQ.png"},"description":"The latest posts from Android Professionals and Google Developer Experts.","subscriberCount":62222,"latestPostsConnection({\"paging\":{\"limit\":1}})":{"__typename":"PostConnection","posts":[{"__ref":"Post:ff7bb40470df"}]},"viewerEdge":{"__ref":"CollectionViewerEdge:collectionId:c72404660798-viewerId:lo_987d513d399f"},"twitterUsername":"proandroiddev","facebookPageId":null,"logo":{"__ref":"ImageMetadata:"}},"User:fbb92b85b19e":{"__typename":"User","id":"fbb92b85b19e"},"User:eac743c05401":{"__typename":"User","id":"eac743c05401"},"User:c6e8e225f7d5":{"__typename":"User","id":"c6e8e225f7d5"},"User:96912518b8bb":{"__typename":"User","id":"96912518b8bb"},"User:d022c4e0f12b":{"__typename":"User","id":"d022c4e0f12b"},"User:6fffa5371f97":{"__typename":"User","id":"6fffa5371f97"},"User:bf87f3641b6c":{"__typename":"User","id":"bf87f3641b6c"},"User:f6e9347ca668":{"__typename":"User","id":"f6e9347ca668"},"ImageMetadata:1*XVtdl45m8YaYrPI4buJ5yQ.png":{"__typename":"ImageMetadata","id":"1*XVtdl45m8YaYrPI4buJ5yQ.png"},"User:9ad99ca649d4":{"__typename":"User","id":"9ad99ca649d4","customDomainState":{"__typename":"CustomDomainState","live":{"__typename":"CustomDomain","domain":"giuliani-arnaud.medium.com"}},"hasSubdomain":true,"username":"giuliani-arnaud"},"Post:ff7bb40470df":{"__typename":"Post","id":"ff7bb40470df","firstPublishedAt":1732672821762,"creator":{"__ref":"User:9ad99ca649d4"},"collection":{"__ref":"Collection:c72404660798"},"isSeries":false,"mediumUrl":"https:\u002F\u002Fproandroiddev.com\u002Fbenchmarking-koin-vs-dagger-hilt-in-modern-android-development-2024-ff7bb40470df","sequence":null,"uniqueSlug":"benchmarking-koin-vs-dagger-hilt-in-modern-android-development-2024-ff7bb40470df"},"LinkedAccounts:e072cea221fc":{"__typename":"LinkedAccounts","mastodon":null,"id":"e072cea221fc"},"UserViewerEdge:userId:e072cea221fc-viewerId:lo_987d513d399f":{"__typename":"UserViewerEdge","id":"userId:e072cea221fc-viewerId:lo_987d513d399f","isFollowing":false,"isUser":false,"isMuting":false},"User:e072cea221fc":{"__typename":"User","id":"e072cea221fc","linkedAccounts":{"__ref":"LinkedAccounts:e072cea221fc"},"isSuspended":false,"imageId":"1*6rI29yuZZDr-3XD0qlJ-RQ.jpeg","mediumMemberAt":0,"verifications":{"__typename":"VerifiedInfo","isBookAuthor":false},"name":"Siddharth Gupta","socialStats":{"__typename":"SocialStats","followerCount":8,"followingCount":3,"collectionFollowingCount":3},"username":"siddh.gupta99","customDomainState":null,"hasSubdomain":false,"bio":"Mobile Developer building CRED","isPartnerProgramEnrolled":false,"viewerEdge":{"__ref":"UserViewerEdge:userId:e072cea221fc-viewerId:lo_987d513d399f"},"viewerIsUser":false,"newsletterV3":null,"postSubscribeMembershipUpsellShownAt":0,"membership":null,"allowNotes":true,"twitterScreenName":""},"Paragraph:b007042f9c2e_0":{"__typename":"Paragraph","id":"b007042f9c2e_0","name":"4e92","type":"H3","href":null,"layout":null,"metadata":null,"text":"Custom modifiers in Jetpack Compose","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"ImageMetadata:1*Oe-DGannPg34NnFtp02TjA.png":{"__typename":"ImageMetadata","id":"1*Oe-DGannPg34NnFtp02TjA.png","originalHeight":1024,"originalWidth":1024,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:b007042f9c2e_1":{"__typename":"Paragraph","id":"b007042f9c2e_1","name":"a4f2","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*Oe-DGannPg34NnFtp02TjA.png"},"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_2":{"__typename":"Paragraph","id":"b007042f9c2e_2","name":"3a16","type":"P","href":null,"layout":null,"metadata":null,"text":"Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the appearance, behaviour, and layout of composable functions without changing their core implementation.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_3":{"__typename":"Paragraph","id":"b007042f9c2e_3","name":"a300","type":"H3","href":null,"layout":null,"metadata":null,"text":"Key aspects of modifiers:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_4":{"__typename":"Paragraph","id":"b007042f9c2e_4","name":"87fb","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Chainable: Modifiers can be chained together, allowing for multiple modifications to be applied sequentially.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":10,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_5":{"__typename":"Paragraph","id":"b007042f9c2e_5","name":"6e91","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Reusable: Custom modifiers can be created and reused across different components, promoting code reusability.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":9,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_6":{"__typename":"Paragraph","id":"b007042f9c2e_6","name":"93cf","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Extensible: Developers can create their own custom modifiers to add specific functionality.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":11,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_7":{"__typename":"Paragraph","id":"b007042f9c2e_7","name":"2a7e","type":"P","href":null,"layout":null,"metadata":null,"text":"The Reusable and Extensible aspects is what make modifiers super powerful. Hence in this blog we’ll be looking at how to create custom modifiers.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_8":{"__typename":"Paragraph","id":"b007042f9c2e_8","name":"ce89","type":"H3","href":null,"layout":null,"metadata":null,"text":"Three Ways","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_9":{"__typename":"Paragraph","id":"b007042f9c2e_9","name":"d877","type":"OLI","href":null,"layout":null,"metadata":null,"text":"composed { }","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_10":{"__typename":"Paragraph","id":"b007042f9c2e_10","name":"12ba","type":"OLI","href":null,"layout":null,"metadata":null,"text":"@composable modifier factory","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_11":{"__typename":"Paragraph","id":"b007042f9c2e_11","name":"bde2","type":"OLI","href":null,"layout":null,"metadata":null,"text":"Modifier.Node API","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_12":{"__typename":"Paragraph","id":"b007042f9c2e_12","name":"9be4","type":"H3","href":null,"layout":null,"metadata":null,"text":"Using composed() to Create Custom Modifiers","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_13":{"__typename":"Paragraph","id":"b007042f9c2e_13","name":"a8b0","type":"P","href":null,"layout":null,"metadata":null,"text":"The composed() function is a convenient way to create custom modifiers in Jetpack Compose. It allows you to define a modifier that can contain composable content.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_14":{"__typename":"Paragraph","id":"b007042f9c2e_14","name":"543f","type":"P","href":null,"layout":null,"metadata":null,"text":"Here’s a basic structure of using composed():","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_15":{"__typename":"Paragraph","id":"b007042f9c2e_15","name":"b025","type":"PRE","href":null,"layout":null,"metadata":null,"text":"fun Modifier.customModifier(\n \u002F\u002F parameters\n) = composed {\n \u002F\u002F Your custom modifier logic here\n \u002F\u002F Can include other composables\n this.then(\n \u002F\u002F Additional modifiers\n )\n}","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":{"__typename":"CodeBlockMetadata","mode":"AUTO","lang":"kotlin"},"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_16":{"__typename":"Paragraph","id":"b007042f9c2e_16","name":"c329","type":"P","href":null,"layout":null,"metadata":null,"text":"Key points about using composed():","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_17":{"__typename":"Paragraph","id":"b007042f9c2e_17","name":"310c","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Composable context: Inside composed{}, you have access to the composable context, allowing you to use other @Composable functions.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":19,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_18":{"__typename":"Paragraph","id":"b007042f9c2e_18","name":"43a0","type":"ULI","href":null,"layout":null,"metadata":null,"text":"State observation: You can observe state and trigger recomposition when needed.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":18,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_19":{"__typename":"Paragraph","id":"b007042f9c2e_19","name":"0cf6","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Chaining: Use this.then() to chain additional modifiers.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":9,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_20":{"__typename":"Paragraph","id":"b007042f9c2e_20","name":"2976","type":"P","href":null,"layout":null,"metadata":null,"text":"Example of a custom modifier using composed():","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"MediaResource:a39afbbefe4c97818f7c85b4c3d9740d":{"__typename":"MediaResource","id":"a39afbbefe4c97818f7c85b4c3d9740d","iframeSrc":"","iframeHeight":0,"iframeWidth":0,"title":""},"Paragraph:b007042f9c2e_21":{"__typename":"Paragraph","id":"b007042f9c2e_21","name":"bc8f","type":"IFRAME","href":null,"layout":"INSET_CENTER","metadata":null,"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":{"__typename":"Iframe","mediaResource":{"__ref":"MediaResource:a39afbbefe4c97818f7c85b4c3d9740d"}},"mixtapeMetadata":null},"Paragraph:b007042f9c2e_22":{"__typename":"Paragraph","id":"b007042f9c2e_22","name":"da7e","type":"P","href":null,"layout":null,"metadata":null,"text":"This example creates a shimmer effect modifier that can be applied to any composable to add a shimmering animation.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_23":{"__typename":"Paragraph","id":"b007042f9c2e_23","name":"cc39","type":"H3","href":null,"layout":null,"metadata":null,"text":"Using @Composable Modifier Factory to Create Custom Modifiers","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_24":{"__typename":"Paragraph","id":"b007042f9c2e_24","name":"d774","type":"P","href":null,"layout":null,"metadata":null,"text":"Another approach to creating custom modifiers in Jetpack Compose is using @Composable modifier factories. This method allows you to create modifiers that can use other @Composable functions and observe state changes.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_25":{"__typename":"Paragraph","id":"b007042f9c2e_25","name":"e025","type":"P","href":null,"layout":null,"metadata":null,"text":"Here’s the basic structure of a @Composable modifier factory:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_26":{"__typename":"Paragraph","id":"b007042f9c2e_26","name":"3292","type":"PRE","href":null,"layout":null,"metadata":null,"text":"@Composable\nfun Modifier.customModifier(\n \u002F\u002F parameters\n): Modifier {\n \u002F\u002F Your custom modifier logic here\n return this.then(\n \u002F\u002F Additional modifiers\n )\n}","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":{"__typename":"CodeBlockMetadata","mode":"AUTO","lang":"kotlin"},"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_27":{"__typename":"Paragraph","id":"b007042f9c2e_27","name":"9e31","type":"P","href":null,"layout":null,"metadata":null,"text":"Key points about using @Composable modifier factories:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_28":{"__typename":"Paragraph","id":"b007042f9c2e_28","name":"859e","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Composable context: The function is marked with @Composable, giving you access to other composable functions and state.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":19,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_29":{"__typename":"Paragraph","id":"b007042f9c2e_29","name":"7ff0","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Return type: The function explicitly returns a Modifier.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":12,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_30":{"__typename":"Paragraph","id":"b007042f9c2e_30","name":"4258","type":"ULI","href":null,"layout":null,"metadata":null,"text":"Flexibility: You can use remember, derivedStateOf, and other composable functions within the modifier.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":12,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_31":{"__typename":"Paragraph","id":"b007042f9c2e_31","name":"9c50","type":"P","href":null,"layout":null,"metadata":null,"text":"Example of a custom modifier using @Composable modifier factory:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"MediaResource:d8a77e731258785c969c7bbd7b7cada2":{"__typename":"MediaResource","id":"d8a77e731258785c969c7bbd7b7cada2","iframeSrc":"","iframeHeight":0,"iframeWidth":0,"title":""},"Paragraph:b007042f9c2e_32":{"__typename":"Paragraph","id":"b007042f9c2e_32","name":"494f","type":"IFRAME","href":null,"layout":"INSET_CENTER","metadata":null,"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":{"__typename":"Iframe","mediaResource":{"__ref":"MediaResource:d8a77e731258785c969c7bbd7b7cada2"}},"mixtapeMetadata":null},"Paragraph:b007042f9c2e_33":{"__typename":"Paragraph","id":"b007042f9c2e_33","name":"c41c","type":"P","href":null,"layout":null,"metadata":null,"text":"This example creates a pulsating scale effect modifier that can be applied to any composable to add a pulsating animation. The scale and duration of the pulse can be customised through parameters.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_34":{"__typename":"Paragraph","id":"b007042f9c2e_34","name":"d86f","type":"BQ","href":null,"layout":null,"metadata":null,"text":"This is an excellent article which explains the key differences b\u002Fw the 2 approaches. Here is the summary:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":21,"end":28,"href":"https:\u002F\u002Fengineering.teknasyon.com\u002Fcomposable-modifier-vs-composed-factory-in-jetpack-compose-6cbb675b0e7b","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":0,"end":106,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_35":{"__typename":"Paragraph","id":"b007042f9c2e_35","name":"989e","type":"BQ","href":null,"layout":null,"metadata":null,"text":"1. Extractability: CMF is limited to use within the Composition scope, while composed() can be extracted and used more flexibly.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":3,"end":17,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":0,"end":3,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_36":{"__typename":"Paragraph","id":"b007042f9c2e_36","name":"6dd1","type":"BQ","href":null,"layout":null,"metadata":null,"text":"2. CompositionLocal resolution: CMF resolves CompositionLocal values at the call site, while composed() resolves them at the usage site.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":3,"end":30,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_37":{"__typename":"Paragraph","id":"b007042f9c2e_37","name":"8e14","type":"BQ","href":null,"layout":null,"metadata":null,"text":"3. State resolution: CMF resolves state only once at the call site, while composed() resolves state at the usage site for each Layout.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":3,"end":19,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_38":{"__typename":"Paragraph","id":"b007042f9c2e_38","name":"db31","type":"BQ","href":null,"layout":null,"metadata":null,"text":"4. Performance: CMF performs better than composed() due to avoiding the expensive materialize() call.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":3,"end":14,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_39":{"__typename":"Paragraph","id":"b007042f9c2e_39","name":"cb56","type":"H3","href":null,"layout":null,"metadata":null,"text":"The Recommended Way: New Modifier.Node API","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_40":{"__typename":"Paragraph","id":"b007042f9c2e_40","name":"17c2","type":"P","href":null,"layout":null,"metadata":null,"text":"As we can see above, creating custom modifiers using composed { } makes more sense than using the CMF approach. Using CMF is ideal when you need inline modifiers or extract a modifier for using it in only one component. On the other hand, composed is useful when designing generic modifiers.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":53,"end":65,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":98,"end":101,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":118,"end":121,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":239,"end":247,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_41":{"__typename":"Paragraph","id":"b007042f9c2e_41","name":"6a9e","type":"P","href":null,"layout":null,"metadata":null,"text":"But here’s the catch, the composed way has few performance issues and the new recommended way of creating custom modifiers is to use the Modifier.Node API.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":26,"end":34,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_42":{"__typename":"Paragraph","id":"b007042f9c2e_42","name":"29d0","type":"BQ","href":null,"layout":null,"metadata":null,"text":"Compose 1.3 introduced the Modifier.Node API where the team has migrated all the pre-defined modifiers to this new API. I would highly recommend to watch this youtube video of Android Dev Summit which explains why this change has been done.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"A","start":154,"end":158,"href":"https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=BjGX2RftXsU","anchorType":"LINK","userId":null,"linkMetadata":null},{"__typename":"Markup","type":"STRONG","start":0,"end":11,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":0,"end":27,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"EM","start":40,"end":240,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_43":{"__typename":"Paragraph","id":"b007042f9c2e_43","name":"1636","type":"P","href":null,"layout":null,"metadata":null,"text":"So if you want the best of both worlds — performance, extractability, skippability, reusable modifiers, use Modifier.Node API","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_44":{"__typename":"Paragraph","id":"b007042f9c2e_44","name":"261d","type":"P","href":null,"layout":null,"metadata":null,"text":"There are three parts to implementing a custom modifier using Modifier.Node:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_45":{"__typename":"Paragraph","id":"b007042f9c2e_45","name":"0337","type":"ULI","href":null,"layout":null,"metadata":null,"text":"A Modifier.Node implementation that holds the logic and state of your modifier.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":2,"end":15,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_46":{"__typename":"Paragraph","id":"b007042f9c2e_46","name":"5309","type":"ULI","href":null,"layout":null,"metadata":null,"text":"A ModifierNodeElement that creates and updates modifier node instances.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":2,"end":21,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_47":{"__typename":"Paragraph","id":"b007042f9c2e_47","name":"c37c","type":"ULI","href":null,"layout":null,"metadata":null,"text":"An optional modifier factory as detailed above.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_48":{"__typename":"Paragraph","id":"b007042f9c2e_48","name":"cecb","type":"P","href":null,"layout":null,"metadata":null,"text":"ModifierNodeElement classes are stateless and new instances are allocated each recomposition, whereas Modifier.Node classes can be stateful and will survive across multiple recompositions, and can even be reused.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":19,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":102,"end":115,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_49":{"__typename":"Paragraph","id":"b007042f9c2e_49","name":"cc01","type":"P","href":null,"layout":null,"metadata":null,"text":"Here is the very basic example of drawing a circle of specific color as shared in the official documentation.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"MediaResource:1c9a583ed459aa358d7c45c415f73a00":{"__typename":"MediaResource","id":"1c9a583ed459aa358d7c45c415f73a00","iframeSrc":"","iframeHeight":0,"iframeWidth":0,"title":""},"Paragraph:b007042f9c2e_50":{"__typename":"Paragraph","id":"b007042f9c2e_50","name":"433c","type":"IFRAME","href":null,"layout":"INSET_CENTER","metadata":null,"text":"","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":{"__typename":"Iframe","mediaResource":{"__ref":"MediaResource:1c9a583ed459aa358d7c45c415f73a00"}},"mixtapeMetadata":null},"Paragraph:b007042f9c2e_51":{"__typename":"Paragraph","id":"b007042f9c2e_51","name":"841d","type":"P","href":null,"layout":null,"metadata":null,"text":"Let’s breakdown to our process","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_52":{"__typename":"Paragraph","id":"b007042f9c2e_52","name":"3a9a","type":"H4","href":null,"layout":null,"metadata":null,"text":"Modifier.Node:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":0,"end":14,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_53":{"__typename":"Paragraph","id":"b007042f9c2e_53","name":"f295","type":"P","href":null,"layout":null,"metadata":null,"text":"The first step is to create a class which implements the Modifier.Node along with DrawModifierNode. There are multiple factory nodes which compose provides out of the box. Here we want to draw something hence we are using the DrawModifierNode. If we wanted to do something with user inputs or gestures we might want to use PointerInputModifierNode","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":57,"end":70,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":82,"end":98,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":226,"end":242,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":323,"end":347,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"ImageMetadata:1*ybo1ri0Ouh63eDGq0R0tsw.png":{"__typename":"ImageMetadata","id":"1*ybo1ri0Ouh63eDGq0R0tsw.png","originalHeight":1900,"originalWidth":1532,"focusPercentX":null,"focusPercentY":null,"alt":null},"Paragraph:b007042f9c2e_54":{"__typename":"Paragraph","id":"b007042f9c2e_54","name":"37e2","type":"IMG","href":null,"layout":"INSET_CENTER","metadata":{"__ref":"ImageMetadata:1*ybo1ri0Ouh63eDGq0R0tsw.png"},"text":"Available nodes to override (image taken from Android Documentation)","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_55":{"__typename":"Paragraph","id":"b007042f9c2e_55","name":"6582","type":"H4","href":null,"layout":null,"metadata":null,"text":"ModifierNodeElement:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"STRONG","start":19,"end":20,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_56":{"__typename":"Paragraph","id":"b007042f9c2e_56","name":"da4f","type":"P","href":null,"layout":null,"metadata":null,"text":"A ModifierNodeElement is an immutable class that holds the data to create or update your custom modifier:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":2,"end":21,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_57":{"__typename":"Paragraph","id":"b007042f9c2e_57","name":"fa41","type":"PRE","href":null,"layout":null,"metadata":null,"text":"\u002F\u002F ModifierNodeElement\nprivate data class CircleElement(val color: Color) : ModifierNodeElement\u003CCircleNode\u003E() {\n override fun create() = CircleNode(color)\n\n override fun update(node: CircleNode) {\n node.color = color\n }\n}","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":{"__typename":"CodeBlockMetadata","mode":"AUTO","lang":"kotlin"},"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_58":{"__typename":"Paragraph","id":"b007042f9c2e_58","name":"9d94","type":"P","href":null,"layout":null,"metadata":null,"text":"ModifierNodeElement implementations need to override the following methods:","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":19,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_59":{"__typename":"Paragraph","id":"b007042f9c2e_59","name":"7f0c","type":"OLI","href":null,"layout":null,"metadata":null,"text":"create: This is the function that instantiates your modifier node. This gets called to create the node when your modifier is first applied. Usually, this amounts to constructing the node and configuring it with the parameters that were passed in to the modifier factory.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":6,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_60":{"__typename":"Paragraph","id":"b007042f9c2e_60","name":"1c8f","type":"OLI","href":null,"layout":null,"metadata":null,"text":"update: This function is called whenever this modifier is provided in the same spot this node already exists, but a property has changed. This is determined by the equals method of the class. The modifier node that was previously created is sent as a parameter to the update call. At this point, you should update the nodes' properties to correspond with the updated parameters. The ability for nodes to be reused this way is key to the performance gains that Modifier.Node brings; therefore, you must update the existing node rather than creating a new one in the update method. In our circle example, the color of the node is updated.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":0,"end":6,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":164,"end":170,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":268,"end":274,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":460,"end":473,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":565,"end":571,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_61":{"__typename":"Paragraph","id":"b007042f9c2e_61","name":"7474","type":"P","href":null,"layout":null,"metadata":null,"text":"Additionally, ModifierNodeElement implementations also need to implement equals and hashCode. update will only get called if an equals comparison with the previous element returns false.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"CODE","start":14,"end":33,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":73,"end":79,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":84,"end":92,"href":null,"anchorType":null,"userId":null,"linkMetadata":null},{"__typename":"Markup","type":"CODE","start":94,"end":100,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_62":{"__typename":"Paragraph","id":"b007042f9c2e_62","name":"aa97","type":"H4","href":null,"layout":null,"metadata":null,"text":"Modifier Factory:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_63":{"__typename":"Paragraph","id":"b007042f9c2e_63","name":"c1dc","type":"P","href":null,"layout":null,"metadata":null,"text":"This is the public API surface of your modifier. Most implementations simply create the modifier element and add it to the modifier chain:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_64":{"__typename":"Paragraph","id":"b007042f9c2e_64","name":"c101","type":"PRE","href":null,"layout":null,"metadata":null,"text":"\u002F\u002F Modifier factory\nfun Modifier.circle(color: Color) = this then CircleElement(color)","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":{"__typename":"CodeBlockMetadata","mode":"AUTO","lang":"kotlin"},"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_65":{"__typename":"Paragraph","id":"b007042f9c2e_65","name":"bb1e","type":"H3","href":null,"layout":null,"metadata":null,"text":"Summary","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_66":{"__typename":"Paragraph","id":"b007042f9c2e_66","name":"cb80","type":"P","href":null,"layout":null,"metadata":null,"text":"In this blog post, we’ve explored the power and flexibility of custom modifiers in Jetpack Compose. We’ve covered three main approaches to creating custom modifiers:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_67":{"__typename":"Paragraph","id":"b007042f9c2e_67","name":"7cb4","type":"OLI","href":null,"layout":null,"metadata":null,"text":"Using the Composable Modifier Function (CMF)","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_68":{"__typename":"Paragraph","id":"b007042f9c2e_68","name":"9fb4","type":"OLI","href":null,"layout":null,"metadata":null,"text":"Using the composed { } function","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_69":{"__typename":"Paragraph","id":"b007042f9c2e_69","name":"d99e","type":"OLI","href":null,"layout":null,"metadata":null,"text":"Using the new Modifier.Node API (recommended)","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_70":{"__typename":"Paragraph","id":"b007042f9c2e_70","name":"c6ae","type":"P","href":null,"layout":null,"metadata":null,"text":"We’ve learned that while CMF and composed { } methods have their uses, the Modifier.Node API is now the recommended approach for creating custom modifiers. This new API offers better performance, reusability, and extensibility.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_71":{"__typename":"Paragraph","id":"b007042f9c2e_71","name":"a8cb","type":"P","href":null,"layout":null,"metadata":null,"text":"Key takeaways:","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_72":{"__typename":"Paragraph","id":"b007042f9c2e_72","name":"2a47","type":"ULI","href":null,"layout":null,"metadata":null,"text":"The Modifier.Node API consists of three main parts: a Modifier.Node implementation, a ModifierNodeElement, and an optional modifier factory.","hasDropCap":null,"dropCapImage":null,"markups":[{"__typename":"Markup","type":"EM","start":4,"end":21,"href":null,"anchorType":null,"userId":null,"linkMetadata":null}],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_73":{"__typename":"Paragraph","id":"b007042f9c2e_73","name":"17a8","type":"ULI","href":null,"layout":null,"metadata":null,"text":"There are various types of modifier nodes available for different purposes, such as DrawModifierNode, LayoutModifierNode, and PointerInputModifierNode.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_74":{"__typename":"Paragraph","id":"b007042f9c2e_74","name":"ba7e","type":"ULI","href":null,"layout":null,"metadata":null,"text":"The ModifierNodeElement is responsible for creating and updating modifier node instances, which can be stateful and survive across recompositions.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_75":{"__typename":"Paragraph","id":"b007042f9c2e_75","name":"b907","type":"ULI","href":null,"layout":null,"metadata":null,"text":"The modifier factory provides a clean, public API for using your custom modifier.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"Paragraph:b007042f9c2e_76":{"__typename":"Paragraph","id":"b007042f9c2e_76","name":"52ba","type":"P","href":null,"layout":null,"metadata":null,"text":"By mastering custom modifiers, especially using the Modifier.Node API, you can create more efficient, reusable, and powerful UI components in your Jetpack Compose applications.","hasDropCap":null,"dropCapImage":null,"markups":[],"codeBlockMetadata":null,"iframe":null,"mixtapeMetadata":null},"CollectionViewerEdge:collectionId:c72404660798-viewerId:lo_987d513d399f":{"__typename":"CollectionViewerEdge","id":"collectionId:c72404660798-viewerId:lo_987d513d399f","isEditor":false,"isMuting":false},"ImageMetadata:":{"__typename":"ImageMetadata","id":"","originalWidth":0,"originalHeight":0},"PostViewerEdge:postId:a950e6f9eb72-viewerId:lo_987d513d399f":{"__typename":"PostViewerEdge","shouldIndexPostForExternalSearch":true,"id":"postId:a950e6f9eb72-viewerId:lo_987d513d399f"},"Tag:android":{"__typename":"Tag","id":"android","displayTitle":"Android","normalizedTagSlug":"android"},"Tag:jetpack-compose":{"__typename":"Tag","id":"jetpack-compose","displayTitle":"Jetpack Compose","normalizedTagSlug":"jetpack-compose"},"Tag:apps":{"__typename":"Tag","id":"apps","displayTitle":"Apps","normalizedTagSlug":"apps"},"Tag:development":{"__typename":"Tag","id":"development","displayTitle":"Development","normalizedTagSlug":"development"},"Tag:tech":{"__typename":"Tag","id":"tech","displayTitle":"Tech","normalizedTagSlug":"tech"},"Post:a950e6f9eb72":{"__typename":"Post","id":"a950e6f9eb72","collection":{"__ref":"Collection:c72404660798"},"content({\"postMeteringOptions\":{}})":{"__typename":"PostContent","isLockedPreviewOnly":false,"bodyModel":{"__typename":"RichText","sections":[{"__typename":"Section","name":"460f","startIndex":0,"textLayout":null,"imageLayout":null,"backgroundImage":null,"videoLayout":null,"backgroundVideo":null}],"paragraphs":[{"__ref":"Paragraph:b007042f9c2e_0"},{"__ref":"Paragraph:b007042f9c2e_1"},{"__ref":"Paragraph:b007042f9c2e_2"},{"__ref":"Paragraph:b007042f9c2e_3"},{"__ref":"Paragraph:b007042f9c2e_4"},{"__ref":"Paragraph:b007042f9c2e_5"},{"__ref":"Paragraph:b007042f9c2e_6"},{"__ref":"Paragraph:b007042f9c2e_7"},{"__ref":"Paragraph:b007042f9c2e_8"},{"__ref":"Paragraph:b007042f9c2e_9"},{"__ref":"Paragraph:b007042f9c2e_10"},{"__ref":"Paragraph:b007042f9c2e_11"},{"__ref":"Paragraph:b007042f9c2e_12"},{"__ref":"Paragraph:b007042f9c2e_13"},{"__ref":"Paragraph:b007042f9c2e_14"},{"__ref":"Paragraph:b007042f9c2e_15"},{"__ref":"Paragraph:b007042f9c2e_16"},{"__ref":"Paragraph:b007042f9c2e_17"},{"__ref":"Paragraph:b007042f9c2e_18"},{"__ref":"Paragraph:b007042f9c2e_19"},{"__ref":"Paragraph:b007042f9c2e_20"},{"__ref":"Paragraph:b007042f9c2e_21"},{"__ref":"Paragraph:b007042f9c2e_22"},{"__ref":"Paragraph:b007042f9c2e_23"},{"__ref":"Paragraph:b007042f9c2e_24"},{"__ref":"Paragraph:b007042f9c2e_25"},{"__ref":"Paragraph:b007042f9c2e_26"},{"__ref":"Paragraph:b007042f9c2e_27"},{"__ref":"Paragraph:b007042f9c2e_28"},{"__ref":"Paragraph:b007042f9c2e_29"},{"__ref":"Paragraph:b007042f9c2e_30"},{"__ref":"Paragraph:b007042f9c2e_31"},{"__ref":"Paragraph:b007042f9c2e_32"},{"__ref":"Paragraph:b007042f9c2e_33"},{"__ref":"Paragraph:b007042f9c2e_34"},{"__ref":"Paragraph:b007042f9c2e_35"},{"__ref":"Paragraph:b007042f9c2e_36"},{"__ref":"Paragraph:b007042f9c2e_37"},{"__ref":"Paragraph:b007042f9c2e_38"},{"__ref":"Paragraph:b007042f9c2e_39"},{"__ref":"Paragraph:b007042f9c2e_40"},{"__ref":"Paragraph:b007042f9c2e_41"},{"__ref":"Paragraph:b007042f9c2e_42"},{"__ref":"Paragraph:b007042f9c2e_43"},{"__ref":"Paragraph:b007042f9c2e_44"},{"__ref":"Paragraph:b007042f9c2e_45"},{"__ref":"Paragraph:b007042f9c2e_46"},{"__ref":"Paragraph:b007042f9c2e_47"},{"__ref":"Paragraph:b007042f9c2e_48"},{"__ref":"Paragraph:b007042f9c2e_49"},{"__ref":"Paragraph:b007042f9c2e_50"},{"__ref":"Paragraph:b007042f9c2e_51"},{"__ref":"Paragraph:b007042f9c2e_52"},{"__ref":"Paragraph:b007042f9c2e_53"},{"__ref":"Paragraph:b007042f9c2e_54"},{"__ref":"Paragraph:b007042f9c2e_55"},{"__ref":"Paragraph:b007042f9c2e_56"},{"__ref":"Paragraph:b007042f9c2e_57"},{"__ref":"Paragraph:b007042f9c2e_58"},{"__ref":"Paragraph:b007042f9c2e_59"},{"__ref":"Paragraph:b007042f9c2e_60"},{"__ref":"Paragraph:b007042f9c2e_61"},{"__ref":"Paragraph:b007042f9c2e_62"},{"__ref":"Paragraph:b007042f9c2e_63"},{"__ref":"Paragraph:b007042f9c2e_64"},{"__ref":"Paragraph:b007042f9c2e_65"},{"__ref":"Paragraph:b007042f9c2e_66"},{"__ref":"Paragraph:b007042f9c2e_67"},{"__ref":"Paragraph:b007042f9c2e_68"},{"__ref":"Paragraph:b007042f9c2e_69"},{"__ref":"Paragraph:b007042f9c2e_70"},{"__ref":"Paragraph:b007042f9c2e_71"},{"__ref":"Paragraph:b007042f9c2e_72"},{"__ref":"Paragraph:b007042f9c2e_73"},{"__ref":"Paragraph:b007042f9c2e_74"},{"__ref":"Paragraph:b007042f9c2e_75"},{"__ref":"Paragraph:b007042f9c2e_76"}]},"validatedShareKey":"","shareKeyCreator":null},"creator":{"__ref":"User:e072cea221fc"},"inResponseToEntityType":null,"isLocked":false,"isMarkedPaywallOnly":false,"lockedSource":"LOCKED_POST_SOURCE_NONE","mediumUrl":"https:\u002F\u002Fproandroiddev.com\u002Fcustom-modifiers-in-jetpack-compose-a950e6f9eb72","primaryTopic":null,"topics":[{"__typename":"Topic","slug":"android-development"}],"isPublished":true,"latestPublishedVersion":"b007042f9c2e","visibility":"PUBLIC","postResponses":{"__typename":"PostResponses","count":0},"clapCount":73,"allowResponses":true,"isLimitedState":false,"title":"Custom modifiers in Jetpack Compose","isSeries":false,"sequence":null,"uniqueSlug":"custom-modifiers-in-jetpack-compose-a950e6f9eb72","socialTitle":"","socialDek":"","canonicalUrl":"","metaDescription":"","latestPublishedAt":1732248697520,"readingTime":4.994654088050315,"previewContent":{"__typename":"PreviewContent","subtitle":"Modifiers in Jetpack Compose are a powerful tool for customising and enhancing UI components. They allow developers to modify the…"},"previewImage":{"__ref":"ImageMetadata:1*Oe-DGannPg34NnFtp02TjA.png"},"isShortform":false,"seoTitle":"","firstPublishedAt":1732248697520,"updatedAt":1732330459568,"shortformType":"SHORTFORM_TYPE_LINK","seoDescription":"","viewerEdge":{"__ref":"PostViewerEdge:postId:a950e6f9eb72-viewerId:lo_987d513d399f"},"isSuspended":false,"license":"ALL_RIGHTS_RESERVED","tags":[{"__ref":"Tag:android"},{"__ref":"Tag:jetpack-compose"},{"__ref":"Tag:apps"},{"__ref":"Tag:development"},{"__ref":"Tag:tech"}],"isNewsletter":false,"statusForCollection":"APPROVED","pendingCollection":null,"detectedLanguage":"en","wordCount":1222,"layerCake":4,"responsesLocked":false}}</script><script src="https://cdn-client.medium.com/lite/static/js/manifest.aa9242f7.js"></script><script src="https://cdn-client.medium.com/lite/static/js/9865.1496d74a.js"></script><script src="https://cdn-client.medium.com/lite/static/js/main.e556b4ac.js"></script><script src="https://cdn-client.medium.com/lite/static/js/instrumentation.d9108df7.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/reporting.ff22a7a5.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/9120.5df29668.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5049.d1ead72d.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/4810.6318add7.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6618.db187378.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2707.b0942613.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/9977.5b3eb23a.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8599.1ab63137.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5250.9f9e01d2.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5787.e66a3a4d.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2648.26563adf.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8393.826a25fb.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/3104.c3413b66.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/3735.afb7e926.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/5642.8ad8a900.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6546.cd03f950.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/6834.08de95de.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7346.72622eb9.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2420.2a5e2d95.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/839.ca7937c2.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7975.d195c6f1.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2106.21ff89d3.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/7394.094844de.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2961.00a48598.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8204.c4082863.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/4391.59acaed3.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/PostPage.MainContent.1387c5dc.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/8414.6565ad5f.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/3974.8d3e0217.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/2527.a0afad8a.chunk.js"></script> <script src="https://cdn-client.medium.com/lite/static/js/PostResponsesContent.36c2ecf4.chunk.js"></script><script>window.main();</script></body></html>

Pages: 1 2 3 4 5 6 7 8 9 10