<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/josip-salkovic/feed/" rel="self" type="application/rss+xml" />
		<link></link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 03 Apr 2026 12:58:20 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8152https://infinum.com/uploads/2021/08/jetpack-compose-native-android-0.webp</url>
				</image>
				<title>Jetpack Compose: A Turning Point for Native Android UI</title>
				<link>https://infinum.com/blog/jetpack-compose-native-android/</link>
				<pubDate>Mon, 16 Aug 2021 14:45:00 +0000</pubDate>
				<dc:creator>Josip Šalković</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/jetpack-compose-native-android/</guid>
				<description>
					<![CDATA[<p>It&#8217;s well on its way to completely replace Google’s existing toolkit.</p>
<p>The post <a href="https://infinum.com/blog/jetpack-compose-native-android/">Jetpack Compose: A Turning Point for Native Android UI</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-352"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	After more than two years of development, Google’s modern toolkit for native UI reached its stable build.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-96">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-97'
	>
	Jetpack Compose is now officially 1.0.</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-99">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-100'
	>
	It’s official: Jetpack Compose is now officially a stable version, but it has actually been used in its pre-release state since 2020 – so much so that there were 2000+ apps using Compose in the Play Store at the time of the official release. I mean, even the Play Store app itself uses it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-102">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-103'
	>
	We’ve <a href="https://infinum.com/blog/jetpack-compose-framework/">introduced Compose’s basics in a previous blog post</a>, so now is the perfect time to concentrate on some of its features in more detail.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	This blog post covers the tool’s core functionality – State. We’ll get into composition and recomposition, stateful composables, making them stateless with state hoisting, and their integration with ViewModel. We’ll also introduce animations to make the UI more alive. Finally, we’ll write instrumental tests to demonstrate how to test Composables.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-109'
	>
	(Re)composition and state management</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-111">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-112'
	>
	State in Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-115'
	>
	State is one of Compose’s core principles, declared as any value that can change over time. Let’s use the example from the previous blog post:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-118"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">Surface</span><span class="token">(shape </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MaterialTheme.shapes.large) {
</span></span><span class="line"><span class="token">       </span><span class="token">Row </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">           </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-121"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-119">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-120'
	>
	Imagine that the composable content above initially only displays the Infinum logo and then a click reveals the word “Infinum”. It’s possible to achieve that effect with the help of State. However, first we need to explain how Composable runs composables (composition) and how it reacts to state changes (recomposition).</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-124"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-122">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-123'
	>
	Composition and recompositon</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-127"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-125">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-126'
	>
	Composition is the tree structure made up of composables used to describe the UI, accomplished by running composables. When we emit a user interface for the first time, that’s the initial composition. During that initial composition, Jetpack Compose tracks the composables that we called to describe the user interface.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-130"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-128">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-129'
	>
	Every time the app’s state changes, a recomposition takes place. It re-runs the composables to update the composition.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-133"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-131">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-132'
	>
	Stateful composables</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-136"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-134">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-135'
	>
	Every composable function has its own memory space. We can store mutable and immutable objects inside that memory space with the composable <em>remember</em>. The value computed by <em>remember</em> is stored in the composition during initial composition, and that stored value is returned during recomposition. If a composable function contains <em>remember</em>, that composable is called statefully composable because it holds a local state.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-137">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-138'
	>
	In our example the goal is to display only the Infinum logo initially and then show the word “Infinum” when a click is performed. We need to store a variable that represents the current state in the composable’s memory: whether the composable is expanded or not. To do this, add the following line inside the beginning of <em>InfinumContent</em>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-141"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">var </span><span class="token">expanded </span><span class="token" style="color: #d73a49;">by</span><span class="token"> </span><span class="token">remember </span><span class="token">{ </span><span class="token">mutableStateOf</span><span class="token">(</span><span class="token" style="color: #005cc5;">false</span><span class="token">) }
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-144"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-142">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-143'
	>
	The expanded boolean value is stored in the composable’s memory by calling <em>remember</em>. The function <em>mutableStateOf</em> used above is just an observable type in Compose. Every time that a value changes, Compose performs a recomposition of any composable function that reads that value. As you can see, during the initial composition our composability is not expanded.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-145">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-146'
	>
	We need to somehow change the expanded value on click. To do this, we add a modifier attribute on <em>Surface</em>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-149"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">Surface</span><span class="token">(
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier</span><span class="token">.clickable </span><span class="token">{
</span></span><span class="line"><span class="token">       expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">!</span><span class="token">expanded
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-152"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-150">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-151'
	>
	Every time a user clicks on the surface, the variable <em>expanded</em> changes. However, no recomposition will take place when <em>expanded</em> changes because we’re not reading that value anywhere. This is the composable <em>Wrap Text</em> with an if-statement that checks the value of <em>expanded</em>:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-154"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">if</span><span class="token"> (expanded) {
</span></span><span class="line"><span class="token">   </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-157"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-155">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-156'
	>
	When the value of <em>expanded</em> changes, a recomposition will be scheduled. Compose is smart enough to update only the if-statement because it has read that value.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-159"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">var </span><span class="token">expanded </span><span class="token" style="color: #d73a49;">by</span><span class="token"> </span><span class="token">remember </span><span class="token">{ </span><span class="token">mutableStateOf</span><span class="token">(</span><span class="token" style="color: #005cc5;">false</span><span class="token">) }
</span></span><span class="line"><span class="token">   </span><span class="token">Surface</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier</span><span class="token">.clickable </span><span class="token">{
</span></span><span class="line"><span class="token">           expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">!</span><span class="token">expanded
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   ) {
</span></span><span class="line"><span class="token">       </span><span class="token">Row</span><span class="token">(
</span></span><span class="line"><span class="token">         </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       ) {
</span></span><span class="line"><span class="token">           </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">              </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (expanded) {
</span></span><span class="line"><span class="token">               </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">                   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">               )
</span></span><span class="line"><span class="token">           }
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-162"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-160"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-161">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/08/jetpack-compose-native-android-1.gif"
					class="image__img block-media__image-img"
					alt=""
										height="320"
															width="640"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-165"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-163">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-164'
	>
	The function <em>remember</em> helps us retain a state through recomposition, but it doesn’t retain a state when a change in configuration occurs. If some data needs to be retained after configuration changes, you need to use <em>rememberSaveable</em>, equivalent to <em>onSaveInstanceState</em> in view-based UI. Of course, the best solution would be to store data inside <em>ViewModel</em>, whose integration will be explained later.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-166">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-167'
	>
	Stateless composables and state hoisting</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-169">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-170'
	>
	Our composable from the previous section <em>InfinumContent</em> is stateful because it holds a state. Stateful composables are hard to test and reuse because they are tightly coupled to that state. Instead, we should make our composables stateless and move that state out of the composable function. We can do that with state hoisting.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-174"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-172">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-173'
	>
	State hoisting is a programming pattern for moving the state higher up in the composition tree, usually to the caller, to make a composable stateless. The easiest way to do that is to replace the state with a function parameter and an event with a lambda function to do a particular action when the value changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-177"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-175">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-176'
	>
	Let’s make our <em>InfinumContent</em> stateless. Add a function parameter of the Boolean type that will represent the state and a lambda function to represent an event to be invoked when the state changes. This is how our <em>InfinumContent</em> looks like now:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-179"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">(expanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">, onExpandedChange</span><span class="token">: (</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) -&gt; </span><span class="token" style="color: #6f42c1;">Unit</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token">Surface</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier</span><span class="token">.clickable </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">onExpandedChange</span><span class="token">(</span><span class="token" style="color: #d73a49;">!</span><span class="token">expanded)
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   ) {
</span></span><span class="line"><span class="token">       </span><span class="token">Row</span><span class="token">(
</span></span><span class="line"><span class="token">          </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       ) {
</span></span><span class="line"><span class="token">           </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">              </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (expanded) {
</span></span><span class="line"><span class="token">               </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">                   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">               )
</span></span><span class="line"><span class="token">           }
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-182"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-180">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-181'
	>
	Change the onCreate method inside MainActivity as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-184"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreate</span><span class="token">(savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onCreate</span><span class="token">(savedInstanceState)
</span></span><span class="line"><span class="token">   </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumComposeAppTheme </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">var </span><span class="token">expanded </span><span class="token" style="color: #d73a49;">by</span><span class="token"> </span><span class="token">rememberSaveable </span><span class="token">{ </span><span class="token">mutableStateOf</span><span class="token">(</span><span class="token" style="color: #005cc5;">false</span><span class="token">) }
</span></span><span class="line"><span class="token">           </span><span class="token">InfinumContent</span><span class="token">(
</span></span><span class="line"><span class="token">               expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> expanded,
</span></span><span class="line"><span class="token">               onExpandedChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> { expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> it }
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-187"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-185">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-186'
	>
	As you can see, the state is hoisted to the caller and we use <em>rememberSaveable</em> instead of remembering because we want to survive configuration changes. Also, pay attention to how we named the lambda function. It’s <em>onExpandedChange</em>, present tense, not <em>onExpandedChanged</em>. The state hasn’t changed yet and a composable function is requesting the event handler to change it. The state moves down (onCreate → InfinumContent) and the event moves up (<em>InfinumContent</em> → <em>onCreate</em>). That pattern is called unidirectional data flow and it’s one of the core principles in the composable world.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-190"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-188">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-189'
	>
	Integration with ViewModel</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-193"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-191">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-192'
	>
	Storing the state inside <em>rememberSaveable</em> is good enough for simple cases. When there are complex data objects involved, a better solution is to store that state inside the <em>ViewModel</em>. Compose provides support for <em>ViewModel</em> integration. We can move our state inside the <em>ViewModel</em>, expose it in an observable holder, and handle events that request state changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-196"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-194">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-195'
	>
	Create the following <em>ViewModel</em> class:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-198"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class MainViewModel</span><span class="token">: </span><span class="token" style="color: #6f42c1;">ViewModel</span><span class="token">() {
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">val </span><span class="token">expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">MutableLiveData</span><span class="token">(</span><span class="token" style="color: #005cc5;">false</span><span class="token">)
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">expandedHolder</span><span class="token">: </span><span class="token" style="color: #6f42c1;">LiveData</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">&gt; </span><span class="token" style="color: #d73a49;">=</span><span class="token"> expanded
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">fun onExpandedChange</span><span class="token">(newExpanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) {
</span></span><span class="line"><span class="token">       expanded.</span><span class="token" style="color: #d73a49;">value</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> newExpanded
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-201"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-199">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-200'
	>
	Refactor <em>onCreate</em> inside <em>MainActivity</em> as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-203"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreate</span><span class="token">(savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onCreate</span><span class="token">(savedInstanceState)
</span></span><span class="line"><span class="token">   </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumComposeAppTheme </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">val </span><span class="token">viewModel </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">viewModel</span><span class="token">(modelClass </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MainViewModel</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">.java)
</span></span><span class="line"><span class="token">           </span><span class="token">val </span><span class="token">expanded </span><span class="token" style="color: #d73a49;">by</span><span class="token"> viewModel.expandedHolder</span><span class="token">.observeAsState</span><span class="token">(</span><span class="token" style="color: #005cc5;">false</span><span class="token">)
</span></span><span class="line"><span class="token">           </span><span class="token">InfinumContent</span><span class="token">(
</span></span><span class="line"><span class="token">               expanded </span><span class="token" style="color: #d73a49;">=</span><span class="token"> expanded,
</span></span><span class="line"><span class="token">               onExpandedChange </span><span class="token" style="color: #d73a49;">=</span><span class="token"> { viewModel</span><span class="token">.onExpandedChange</span><span class="token">(it) }
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-206"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-204">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-205'
	>
	Compose provides the function <em>viewModel()</em> for getting an instance of the provided <em>ViewModel</em> class. The function follows the lifecycle of the caller by default, in this case Activity. The variable expanded is obtained by exposing <em>LiveData</em> inside the <em>ViewModel</em> and it’s observed as State. A state is another observable type that Jetpack Compose can use directly. The function <em>observeAsState</em> observes <em>LiveData</em> and returns a State object that is updated whenever <em>LiveData</em> changes. The parameter “by” is just the Kotlin syntactic way for unwrapping the returned value from State, in this context, Boolean.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-209"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-207">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-208'
	>
	Animations in Jetpack Compose</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-212"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-210">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-211'
	>
	Overview</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-215"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-213">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-214'
	>
	Animations are great tools in modern app development that help us build a more creative and better user interface. Jetpack Compose provides an API for easier animation implementation. The animation API in Compose is divided into two sections:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-218"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-216">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-217'
	>
	<li>High-level animation API – contains common animation patterns used across the app and is most suitable for Material Design Motion</li><li>Low-level animation API – gives more control and customization options and is built with Kotlin coroutine suspending functions</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-221"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-219">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-220'
	>
	In this article, we’ll cover only the High-level animation API. You can find out more about low-level APIs <a href="https://developer.android.com/jetpack/compose/animation#low-level-apis">here</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-224"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-222">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-223'
	>
	AnimatedVisibility (experimental)</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-227"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-225">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-226'
	>
	The <em>AnimatedVisibility</em> composable animates the appearance and disappearance of its content. By default, content appears by fading in and expanding, and disappears by fading out and shrinking. Keep in mind that this is an experimental API so it might change in the future or be completely removed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-230"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-228">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-229'
	>
	Replace the if-statement inside InfinumContent with AnimatedVisibiliy as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-232"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">(expanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">, onExpandedChange</span><span class="token">: (</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) -&gt; </span><span class="token" style="color: #6f42c1;">Unit</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   </span><span class="token">AnimatedVisibility</span><span class="token">(visible </span><span class="token" style="color: #d73a49;">=</span><span class="token"> expanded) {
</span></span><span class="line"><span class="token">               </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">                   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">               )
</span></span><span class="line"><span class="token">           }
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-235"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-233"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-234">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/08/jetpack-compose-native-android-2.gif"
					class="image__img block-media__image-img"
					alt=""
										height="172"
															width="528"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-238"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-236">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-237'
	>
	AnimateContentSize</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-241"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-239">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-240'
	>
	As its name says, <em>AnimateContentSize</em> animates the size changes of the called composable. Inside <em>InfinumContent</em>, add the <em>animateContentSize</em> modifier to the composable you want to animate:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-243"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">(expanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">, onExpandedChange</span><span class="token">: (</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) -&gt; </span><span class="token" style="color: #6f42c1;">Unit</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token">Column</span><span class="token">(
</span></span><span class="line"><span class="token">     </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   ) {
</span></span><span class="line"><span class="token">       </span><span class="token">Card</span><span class="token">(
</span></span><span class="line"><span class="token">           modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">               </span><span class="token">.animateContentSize</span><span class="token">()
</span></span><span class="line"><span class="token">       ) {
</span></span><span class="line"><span class="token">          </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-246"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-244"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-245">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/08/jetpack-compose-native-android-3.gif"
					class="image__img block-media__image-img"
					alt=""
										height="172"
															width="528"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-249"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-247">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-248'
	>
	Crossfade</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-252"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-250">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-251'
	>
	Crossfade animates the switch between two layouts with a crossfade effect. Let’s say we want to accomplish that between the non-expanded state only showing the Infinum logo composable and the expanded state that shows only the Infinum text composable. Switching between these composables needs to be done with a crossfade. Refactor <em>InfinumContent</em> in the following way:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-254"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">(expanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">, onExpandedChange</span><span class="token">: (</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) -&gt; </span><span class="token" style="color: #6f42c1;">Unit</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token">Column</span><span class="token">(
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   ) {
</span></span><span class="line"><span class="token">       </span><span class="token">Card</span><span class="token">(
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       ) {
</span></span><span class="line"><span class="token">           </span><span class="token">Row</span><span class="token">(
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           ) {
</span></span><span class="line"><span class="token">               </span><span class="token">Crossfade</span><span class="token">(targetState </span><span class="token" style="color: #d73a49;">=</span><span class="token"> expanded) {
</span></span><span class="line"><span class="token">                   </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (it) {
</span></span><span class="line"><span class="token">                       </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">                          </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">                       )
</span></span><span class="line"><span class="token">                   } </span><span class="token" style="color: #d73a49;">else</span><span class="token"> {
</span></span><span class="line"><span class="token">                       </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">                          </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">                       )
</span></span><span class="line"><span class="token">                   }
</span></span><span class="line"><span class="token">               }
</span></span><span class="line"><span class="token">           }
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-257"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-255">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-256'
	>
	Testing a Compose layout</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-260"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-258">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-259'
	>
	Overview</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-263"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-261">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-262'
	>
	Testing a Compose layout is substantially different than testing view-based UI. View-based UI architecture defines what the view is. The view occupies its space on screen and has attributes such as the identifier, margins, padding, etc.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-264">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-265'
	>
	On the other hand, composables are functions that emit pieces of UI. They don’t have attributes or identifiers to distinguish them by. We will test our sample by introducing semantics.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-267">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-268'
	>
	Semantics</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-270">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-271'
	>
	We need a way to identify our composables. Semantics, as the name implies, gives meaning to a piece of UI, it describes it. Semantics are generated alongside the UI hierarchy emitted on screen. A piece of UI in semantics can be anything, from a whole screen to just a single composable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-275"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-273">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-274'
	>
	Testing the InfinumContent composable</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-278"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-276">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-277'
	>
	Compose tests are instrumented tests that will be executed on an Android device. To perform this test, create the <em>InfinumLogoTest</em> class inside the <em>androidTest</em> folder as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-280"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@RunWith</span><span class="token">(AndroidJUnit4</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">)
</span></span><span class="line"><span class="token">class InfinumLogoTest </span><span class="token">{
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #6f42c1;">@get</span><span class="token">:</span><span class="token" style="color: #6f42c1;">Rule</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">composeTestRule </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">createAndroidComposeRule</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">MainActivity</span><span class="token">&gt;</span><span class="token">()
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-283"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-281">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-282'
	>
	We are creating <em>composeTestRule</em> by calling <em>createAndroidComposeRule</em> with the given activity. With this rule, we can use Compose functionalities or access the Activity directly if we need to.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-286"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-284">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-285'
	>
	We want to check if only the logo is displayed initially. Since the logo is an Image composable and it must have the <em>contentDescription</em> attribute, this would be our testing method:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-288"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Test</span><span class="token">
</span></span><span class="line"><span class="token">fun logo_initially_displayed</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">infinumLogo </span><span class="token" style="color: #d73a49;">=</span><span class="token"> composeTestRule.activity</span><span class="token">.getString</span><span class="token">(R.string.infinum_mark_description)
</span></span><span class="line"><span class="token">   composeTestRule</span><span class="token">.onNodeWithContentDescription</span><span class="token">(infinumLogo)</span><span class="token">.assertIsDisplayed</span><span class="token">()
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-291"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-289">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-290'
	>
	We use <em>composeTestRule</em> to access the Activity directly to fetch the String that represents the Image content description. We then call the function <em>onNodeWithContentDescription()</em> with a given String, which will try to find a semantic node with that description. And finally, we call <em>assertIsDisplayed()</em> on that semantic node representing the Infinum logo. Our test is successful!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-294"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-292">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-293'
	>
	Next, we test to confirm that the text doesn’t initially exist inside the composition. Let’s use this method:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-296"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Test</span><span class="token">
</span></span><span class="line"><span class="token">fun text_initially_not_exist</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">infinumText </span><span class="token" style="color: #d73a49;">=</span><span class="token"> composeTestRule.activity</span><span class="token">.getString</span><span class="token">(R.string.infinum)
</span></span><span class="line"><span class="token">   composeTestRule</span><span class="token">.onNodeWithText</span><span class="token">(infinumText)</span><span class="token">.assertDoesNotExist</span><span class="token">()
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-299"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-297">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-298'
	>
	Since the <em>Text</em> composable doesn’t have a content description, we can’t use the <em>onNodeWithContentDescription()</em> function. Instead, we can use <em>onNodeWithText()</em> with the provided text and then call <em>assertDoesNotExist()</em>. Another success!</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-302"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-300">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-301'
	>
	Finally, we want to test that the text is displayed when a click is performed. Our clickable composable inside <em>InfinumContent</em> is a Card. A card doesn’t have a text or content description. We need to somehow tag that component to use it inside our test class.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-305"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-303">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-304'
	>
	Let’s declare our tag for that <em>Card</em> composable:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-307"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">const</span><span class="token"> </span><span class="token">val </span><span class="token">INFINUM_CARD </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">Infinum Card</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-310"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-308">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-309'
	>
	Connect the composable <em>Card</em> with the declared tag as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-312"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">(expanded</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">, onExpandedChange</span><span class="token">: (</span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token">) -&gt; </span><span class="token" style="color: #6f42c1;">Unit</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token">Card</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           </span><span class="token">.testTag</span><span class="token">(INFINUM_CARD)
</span></span><span class="line"><span class="token">   ) {
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-315"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-313">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-314'
	>
	Our test function then looks like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-317"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Test</span><span class="token">
</span></span><span class="line"><span class="token">fun text_displayed_when_click_performed</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">infinumText </span><span class="token" style="color: #d73a49;">=</span><span class="token"> composeTestRule.activity</span><span class="token">.getString</span><span class="token">(R.string.infinum)
</span></span><span class="line"><span class="token">   composeTestRule</span><span class="token">.onNodeWithTag</span><span class="token">(INFINUM_CARD)</span><span class="token">.performClick</span><span class="token">()
</span></span><span class="line"><span class="token">   composeTestRule</span><span class="token">.onNodeWithText</span><span class="token">(infinumText)</span><span class="token">.assertIsDisplayed</span><span class="token">()
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-320"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-318">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-319'
	>
	Now we are calling the <em>onNodeWithTag()</em> function with a given tag, and simulating the click event by calling the <em>performClick()</em> method. After that, we are checking to see if the text “Infinum” is displayed. Again, it passed the test.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-323"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-321"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-322">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/08/jetpack-compose-native-android-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="427"
															width="1135"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			the output in android studio		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-326"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-324">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-325'
	>
	Jetpack Compose pros &amp; cons</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-329"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-327">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-328'
	>
	Jetpack Compose is a powerful tool for building native Android UI. A major advantage of the declarative approach is that we just describe the UI and Compose takes care of the rest as the app state changes. This example showed how quick and easy it is to build the Infinum logo, style it and animate it on click. In other words, you can do more with less code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-332"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-330">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-331'
	>
	The preview feature in Android Studio is an unquestionable development accelerator because you can immediately see how the UI is going to look like. Plus, with interactive mode, you can perform clicks and see the changes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-335"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-333">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-334'
	>
	Furthermore, Compose is interoperable with existing view-based UI so we can quickly switch between the two. This feature comes in handy for migrating a project to Compose because migrating an entire app at once is not a small task.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-338"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-336">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-337'
	>
	Compose also provides us with other great features such as the built-in Material Design support for styling, Dark Theme support, powerful Animation API for creating a livelier UI, etc.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-341"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-339">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-340'
	>
	On the other hand, integration with other Jetpack components could also be better. Some views inside view-based UI don’t exist in Compose so we need to use AndroidView and custom solutions. Lack of support for most popular libraries nowadays is also a disadvantage.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-344"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-342">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-343'
	>
	Jetpack Compose – looking forward</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-347"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-345">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-346'
	>
	Overall, the previous Android UI toolkit was not sustainable. The API started showing signs of aging, it was tightly coupled with Android OS, not Kotlin based, and lacked Material Design support. Just looking at the base Android View class, we can see that there are over 30,000 lines of code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-350"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-348">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-349'
	>
	Jetpack Compose is an enormous turning point for building native Android UI, not just from the practical side, but in the way we think about it. With the stable version, it’s well on its way to completely replacing Google’s existing toolkit.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/jetpack-compose-native-android/">Jetpack Compose: A Turning Point for Native Android UI</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7958https://infinum.com/uploads/2021/05/jetpack-compose-framework-0.webp</url>
				</image>
				<title>Android, Meet Jetpack Compose!</title>
				<link>https://infinum.com/blog/jetpack-compose-framework/</link>
				<pubDate>Fri, 21 May 2021 11:20:00 +0000</pubDate>
				<dc:creator>Josip Šalković</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/jetpack-compose-framework/</guid>
				<description>
					<![CDATA[<p>Jetpack Compose is a modern declarative framework designed for building a native Android user interface.</p>
<p>The post <a href="https://infinum.com/blog/jetpack-compose-framework/">Android, Meet Jetpack Compose!</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-616"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-353">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-356"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-354">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-355'
	>
	Are you looking for a modern declarative framework designed for building a native Android user interface? Jetpack Compose makes writing and maintaining our UI easier, features Material Design support for theming, is compatible with the existing view-based architecture, and is built entirely on top of Kotlin.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-359"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-357">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-358'
	>
	On the recently hosted I/O, Google announced that <a href="https://android-developers.googleblog.com/2021/05/whats-new-for-android-developers-at.html">Jetpack Compose would hit the stable version in July</a>, so the time is right to get up to speed.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-362"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-360">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-361'
	>
	What is a declarative framework?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-365"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-363">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-364'
	>
	Usually, an Android view is a tree representation of widgets. As the application state changes due to various user events, we must update the widgets accordingly. The most common way to do that is to walk the tree using functions like <strong><code>findViewById()</code></strong> and change the internal state of the widget.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-368"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-366">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-367'
	>
	Manual manipulation of views increases the possibility of state inconsistency. Imagine that you have a complex UI with a lot of <strong><code>TextViews</code></strong>, <strong><code>Buttons</code></strong>, and <strong><code>ImageViews</code></strong>. Application state changes and user interface needs to be updated. If we forget to update at least one widget that should be updated with new data, the result is inconsistency between states. And here comes a declarative UI model to the rescue.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-371"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-369">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-370'
	>
	A declarative UI model regenerates an entire screen from scratch when the state changes. With this approach, we avoid the complexity of manually updating the view-based hierarchy and also reduce potentially forgotten updated views.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-376"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="blockquote block-blockquote__blockquote" data-id="es-372">
	
	<div class="blockquote__content">
		<i
	class="icon blockquote__icon icon--size-16 icon--scale-100"
	 aria-hidden='true' data-name='blockquote-24' data-id='es-373'>
	<svg fill='none' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path clip-rule='evenodd' d='m12 24c6.6274 0 12-5.3726 12-12 0-2.79685-.9568-5.37021-2.561-7.41062-.581.22951-1.0832.60583-1.5069 1.12898-.5132.60844-.7698 1.41969-.7698 2.43375v.07605h2.5789v5.59004h-5.6197v-5.01962c0-1.11547.154-2.06616.4619-2.85205.3336-.81125.757-1.48307 1.2702-2.01545.528-.52161 1.1175-.92155 1.7687-1.1998-2.0728-1.70651-4.7279-2.73128-7.6223-2.73128-6.62742 0-12 5.37258-12 12 0 6.6274 5.37258 12 12 12zm-3.53811-18.05347c-.30793.78589-.46189 1.73658-.46189 2.85205v5.01962h5.6197v-5.59004h-2.5789v-.07605c0-1.01406.2566-1.82531.7698-2.43375.5389-.63379 1.1804-1.05209 1.9245-1.2549v-2.28164c-.7441.07605-1.4626.25351-2.1555.53238-.6928.27887-1.3086.68449-1.84752 1.21688-.51321.53238-.9366 1.2042-1.27019 2.01545z' fill='currentColor' fill-rule='evenodd'/></svg></i><p	class='typography typography--size-36-text js-typography blockquote__quote'
	data-id='es-374'
	>
	Regenerating the entire screen is expensive, and Jetpack Compose is smart enough to detect which parts of the user interface need to be redrawn at any time.</p>
		<div class="blockquote__caption-wrap">
					</div>
	</div>
</div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-379"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-377">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-378'
	>
	Styling in Jetpack Compose: Layouts and theming</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-382"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-380">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-381'
	>
	Before diving deeper into Jetpack Compose, you must <a href="https://developer.android.com/studio/preview">download and install the latest beta version of Android Studio Preview</a> to use Compose functionalities. The latest beta version of Android Studio Preview provides core features such as a New Project template for Compose and the ability to preview Composable functions.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-385"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-383">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-384'
	>
	Jetpack Compose Setup</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-388"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-386">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-387'
	>
	If you want to start a new project, navigate to templates, select Empty Compose Activity, and IDE will do the rest.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-391"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-389">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-390'
	>
	If you want to integrate Compose into an existing project, you must configure your project with the required settings and dependencies.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-394"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-392">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-393'
	>
	Make sure that you are using Kotlin 1.4.30 or newer inside your project:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-396"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">buildscript </span><span class="token">{
</span></span><span class="line"><span class="token">    </span><span class="token">ext </span><span class="token">{
</span></span><span class="line"><span class="token">        kotlin_version </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.4.32</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">        compose_version </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.0.0-beta07</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">    </span><span class="token">dependencies </span><span class="token">{
</span></span><span class="line"><span class="token">        classpath </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">org.jetbrains.kotlin:kotlin-gradle-plugin:</span><span class="token" style="color: #005cc5;">$kotlin_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-399"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-397">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-398'
	>
	Next, ensure the minimum supported API version is set to 21 or higher, as shown below. Also, do not forget to enable the Jetpack Compose feature, set the Kotlin compiler settings, and add Compose-related dependencies:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-401"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">android </span><span class="token">{
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">defaultConfig </span><span class="token">{
</span></span><span class="line"><span class="token">        minSdkVersion </span><span class="token" style="color: #005cc5;">21</span><span class="token">
</span></span><span class="line"><span class="token">                </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">compileOptions </span><span class="token">{
</span></span><span class="line"><span class="token">        sourceCompatibility JavaVersion.VERSION_1_8
</span></span><span class="line"><span class="token">        targetCompatibility JavaVersion.VERSION_1_8
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">kotlinOptions </span><span class="token">{
</span></span><span class="line"><span class="token">        jvmTarget </span><span class="token" style="color: #d73a49;">=</span><span class="token"> JavaVersion.VERSION_1_8
</span></span><span class="line"><span class="token">        useIR </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">true</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">buildFeatures </span><span class="token">{
</span></span><span class="line"><span class="token">        compose </span><span class="token" style="color: #005cc5;">true</span><span class="token">
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">composeOptions </span><span class="token">{
</span></span><span class="line"><span class="token">        kotlinCompilerExtensionVersion compose_version
</span></span><span class="line"><span class="token">        kotlinCompilerVersion kotlin_version
</span></span><span class="line"><span class="token">    }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">dependencies </span><span class="token">{
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.compose.ui:ui:</span><span class="token" style="color: #005cc5;">$compose_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.compose.material:material:</span><span class="token" style="color: #005cc5;">$compose_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.compose.ui:ui-tooling:</span><span class="token" style="color: #005cc5;">$compose_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.compose.runtime:runtime-livedata:</span><span class="token" style="color: #005cc5;">$compose_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token">androidTestImplementation</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.compose.ui:ui-test-junit4:</span><span class="token" style="color: #005cc5;">$compose_version</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">)
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.activity:activity-compose:1.3.0-alpha08</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">    implementation </span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha05</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">        </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-404"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-402">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-403'
	>
	Getting started with Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-407"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-405">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-406'
	>
	Let’s look at an example including a simple image and the corresponding text emitted on screen. To do that, we need to call composable functions from the <strong><code>setContent</code></strong> block. Composable functions are regular functions annotated with <strong><code>@Composable</code></strong>, emitting UI elements and showing them on screen.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-410"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-408">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-409'
	>
	You must annotate all composable functions with <strong><code>@Composable</code></strong> because it tells the Compose compiler that the function is intended to convert data into UI. Composable functions don’t return anything, they only describe some piece of UI, and are written with the first uppercase letter.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-413"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-411">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-412'
	>
	Declare the following composable function:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-415"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">       painter </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">painterResource</span><span class="token">(id </span><span class="token" style="color: #d73a49;">=</span><span class="token"> R.drawable.ic_infinum_mark),
</span></span><span class="line"><span class="token">       contentDescription </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">stringResource</span><span class="token">(id </span><span class="token" style="color: #d73a49;">=</span><span class="token"> R.string.infinum_mark_description)
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">   </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">       text </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">stringResource</span><span class="token">(id </span><span class="token" style="color: #d73a49;">=</span><span class="token"> R.string.infinum)
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-418"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-416">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-417'
	>
	<strong><code>Text</code></strong> is a composable function that emits text on the screen and its <strong><code>TextView</code></strong> equivalent in regular view-based UI. <strong><code>Image</code></strong> is a composable function for emitting images on screen, and it is equivalent to <strong><code>ImageView</code></strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-421"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-419">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-420'
	>
	Open or create <strong><code>MainActivity</code></strong> and paste the following:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-423"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">class MainActivity </span><span class="token">: </span><span class="token" style="color: #6f42c1;">AppCompatActivity</span><span class="token">() {
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreate</span><span class="token">(savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onCreate</span><span class="token">(savedInstanceState)
</span></span><span class="line"><span class="token">       </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">          </span><span class="token">InfinumContent</span><span class="token">()
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-426"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-424">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-425'
	>
	<strong><code>setContent</code></strong> is the composable equivalent to <strong><code>setContentView</code></strong>. It composes given composables inside the block. This means that the content declared inside the block will become the root view of a given activity; in this example <strong><code>MainActivity</code></strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-429"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-427"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-428">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="672"
															width="947"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Output on the emulator		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-432"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-430">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-431'
	>
	Previewing layouts with Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-435"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-433">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-434'
	>
	Instead of running the project every time a change occurs, Android Studio provides a feature for previewing layouts and how they will appear on screen. Declare another composable function and annotate it with <strong><code>@Preview</code></strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-438"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-436">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-437'
	>
	Within it, call a composable function that you initially want to inspect. Preview composable functions don’t accept parameters. If we want to inspect how <strong><code>InfinumContent</code></strong> shows on screen, we can achieve this by declaring the preview composable function as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-440"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Preview</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun PreviewInfinumContent</span><span class="token">() </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">InfinumContent</span><span class="token">()
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-443"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-441"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-442">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2021/04/jetpack-compose-framework-2-1400x682.webp				media='(max-width: 699px)'
				type=image/webp								height="682"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="779"
															width="1600"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Android Studio will automatically generate The preview layout for you.		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-446"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-444">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-445'
	>
	Basic layouts in Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-449"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-447">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-448'
	>
	Now that we have learned how to create a simple view, we can discuss possible layout variations. Jetpack Compose provides a<strong><code>Row</code></strong>, composable layout that places its children in a horizontal sequence. It is equivalent to <strong><code>LinearLayout</code></strong> with horizontal orientation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-452"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-450">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-451'
	>
	For a vertical sequence of children, there is a <strong><code>Column</code></strong> composable. It is equivalent to <strong><code>LinearLayout</code></strong> with vertical orientation. In this example, we want the text to show after the logo and we can achieve that by writing the following snippet:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-454"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">Row</span><span class="token">(verticalAlignment </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Alignment.CenterVertically) {
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-457"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-455"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-456">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2021/04/jetpack-compose-framework-3-1400x491.webp				media='(max-width: 699px)'
				type=image/webp								height="491"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="561"
															width="1600"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Corresponding preview of the InfinumContent composable.		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-460"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-458">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-459'
	>
	Other layouts that we will use often are:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-463"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-461">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-462'
	>
	<li><strong><code>Box</code></strong> – allows us to have items behind and/or in front of others and it is equivalent to <code>FrameLayout</code> in view-based UI<ul><li><strong><code>ConstraintLayout</code></strong> – helps us place composables relative to others on the screen and as the name implies, equivalent to the same layout in view-based UI</li></ul><ul><li><strong><code>LazyColumn</code></strong> – <code>RecyclerView</code> with <code>LinearLayoutManager</code> equivalent in view-based UI</li></ul><ul><li><strong><code>LazyRow</code></strong> – <code>RecyclerView</code> with <code>LinearLayoutManager.HORIZONTAL</code> equivalent in view-based UI</li></ul></li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-466"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-464">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-465'
	>
	Theming in Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-469"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-467">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-468'
	>
	The previous section shows how quickly we can build a piece of UI with Jetpack Compose. Moving on to cover theming in Compose, it comes with Material Design built-in support which is easy to customize. In case you are unfamiliar with Material Design, it is a design system for digital interfaces that is comprised of colors, typography, and shape attributes.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-472"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-470">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-471'
	>
	Colors in Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-475"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-473">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-474'
	>
	The usual practice in Compose is to declare colors inside the <strong><code>Color.kt</code></strong> file, which is equivalent to <strong><code>colors.xml</code></strong> in view-based UI.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-478"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-476">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-477'
	>
	Create the file and define just one custom red color variant as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-480"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">val </span><span class="token">InfinumRed </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">Color</span><span class="token">(</span><span class="token" style="color: #005cc5;">0xFFD9262B</span><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-483"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-481">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-482'
	>
	Jetpack Compose provides support for Light and Dark Theme, leaving you to declare which colors will be displayed where. It is best to put everything theme-related inside the <strong><code>Theme.kt</code></strong> file which is equivalent to <strong><code>themes.xml</code></strong> in view-based UI.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-486"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-484">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-485'
	>
	We will define our Dark and Light Color palettes, put them inside the file mentioned above and use the defined custom color and other default ones:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-488"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">val </span><span class="token">DarkColorPalette </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">darkColors</span><span class="token">(
</span></span><span class="line"><span class="token">   primary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   primaryVariant </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   secondary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   background </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.Black,
</span></span><span class="line"><span class="token">   surface </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.DarkGray,
</span></span><span class="line"><span class="token">   onPrimary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   onSecondary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   onBackground </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   onSurface </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">private</span><span class="token"> </span><span class="token">val </span><span class="token">LightColorPalette </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">lightColors</span><span class="token">(
</span></span><span class="line"><span class="token">   primary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   primaryVariant </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   secondary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> InfinumRed,
</span></span><span class="line"><span class="token">   background </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   surface </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   onPrimary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.White,
</span></span><span class="line"><span class="token">   onSecondary </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.Black,
</span></span><span class="line"><span class="token">   onBackground </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.Black,
</span></span><span class="line"><span class="token">   onSurface </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Color.Black
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-491"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-489">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-490'
	>
	In the same <strong><code>Theme.kt</code></strong> file, wrap everything into the composable function which we will call everywhere to apply custom theming:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-493"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumComposeAppTheme</span><span class="token">(
</span></span><span class="line"><span class="token">   darkTheme</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">isSystemInDarkTheme</span><span class="token">(),
</span></span><span class="line"><span class="token">   content</span><span class="token">: </span><span class="token" style="color: #6f42c1;">@Composable</span><span class="token"> () </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> Unit
</span></span><span class="line"><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token">val </span><span class="token">colors </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #d73a49;">if</span><span class="token"> (darkTheme) {
</span></span><span class="line"><span class="token">       DarkColorPalette
</span></span><span class="line"><span class="token">   } </span><span class="token" style="color: #d73a49;">else</span><span class="token"> {
</span></span><span class="line"><span class="token">       LightColorPalette
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">MaterialTheme</span><span class="token">(
</span></span><span class="line"><span class="token">       colors </span><span class="token" style="color: #d73a49;">=</span><span class="token"> colors,
</span></span><span class="line"><span class="token">       content </span><span class="token" style="color: #d73a49;">=</span><span class="token"> content
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-496"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-494">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-495'
	>
	Now, add the composable function above inside <strong><code>setContent</code></strong> before emitting content:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-498"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreate</span><span class="token">(savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onCreate</span><span class="token">(savedInstanceState)
</span></span><span class="line"><span class="token">   </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumComposeAppTheme </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">InfinumContent</span><span class="token">()
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-501"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-499">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-500'
	>
	By calling <strong><code>InfinumComposeAppTheme</code></strong> before emitting content, we explicitly say that we want to use Material Design attributes from that custom composable function. It is similar to declaring an application theme inside in a regular view-based UI.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-504"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-502">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-503'
	>
	Finally, add color attributes to our <strong><code>InfinumContent</code></strong> composable function to get the effect:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-506"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">Row</span><span class="token">(Modifier</span><span class="token">.background</span><span class="token">(MaterialTheme.colors.background)) {
</span></span><span class="line"><span class="token">       </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           colorFilter </span><span class="token" style="color: #d73a49;">=</span><span class="token"> ColorFilter</span><span class="token">.tint</span><span class="token">(InfinumRed)
</span></span><span class="line"><span class="token">       )
</span></span><span class="line"><span class="token">       </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           color </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MaterialTheme.colors.onBackground
</span></span><span class="line"><span class="token">       )
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-509"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-507"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-508">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="971"
															width="1391"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Preview with custom colors for both Light and Dark Mode		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-512"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-510">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-511'
	>
	Typography in Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-515"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-513">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-514'
	>
	Regarding typography and how to show custom fonts, the best practice in Jetpack Compose is to put all typography-related stuff into the<strong><code>Type.kt</code></strong> file. Create the file and declare a custom font family as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-517"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">val </span><span class="token">GTHaptik </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">FontFamily</span><span class="token">(
</span></span><span class="line"><span class="token">   </span><span class="token">Font</span><span class="token">(R.font.gt_haptik_regular, FontWeight.Normal),
</span></span><span class="line"><span class="token">   </span><span class="token">Font</span><span class="token">(R.font.gt_haptik_bold, FontWeight.Bold)
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-520"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-518">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-519'
	>
	Inside the same file, create the typography object with an upper font family. For simplicity, we only use the <strong><code>h2</code></strong> style:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-522"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">val </span><span class="token">Typography </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">Typography</span><span class="token">(
</span></span><span class="line"><span class="token">   h2 </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">TextStyle</span><span class="token">(
</span></span><span class="line"><span class="token">       fontFamily </span><span class="token" style="color: #d73a49;">=</span><span class="token"> GTHaptik,
</span></span><span class="line"><span class="token">       fontWeight </span><span class="token" style="color: #d73a49;">=</span><span class="token"> FontWeight.Bold,
</span></span><span class="line"><span class="token">       fontSize </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">60</span><span class="token">.sp,
</span></span><span class="line"><span class="token">       letterSpacing </span><span class="token" style="color: #d73a49;">=</span><span class="token"> (</span><span class="token" style="color: #d73a49;">-</span><span class="token" style="color: #005cc5;">0.5</span><span class="token">).sp
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-525"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-523">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-524'
	>
	Inside the <strong><code>Theme.kt</code></strong> file, update <strong><code>InfinumComposeAppTheme</code></strong> with the previously declared typography attribute:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-527"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumComposeAppTheme</span><span class="token">(
</span></span><span class="line"><span class="token">   darkTheme</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">isSystemInDarkTheme</span><span class="token">(),
</span></span><span class="line"><span class="token">   content</span><span class="token">: </span><span class="token" style="color: #6f42c1;">@Composable</span><span class="token"> () </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> Unit
</span></span><span class="line"><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   </span><span class="token">MaterialTheme</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       typography </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Typography
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-530"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-528">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-529'
	>
	Inside <strong><code>InfinumContent</code></strong> add style to <strong><code>Text</code></strong> composable to get the effect:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-532"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">           </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           style </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MaterialTheme.typography.h2
</span></span><span class="line"><span class="token">       )
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-535"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-533"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-534">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2021/04/jetpack-compose-framework-5-1400x884.webp				media='(max-width: 699px)'
				type=image/webp								height="884"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-5.webp"
					class="image__img block-media__image-img"
					alt=""
										height="946"
															width="1498"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Preview with custom typography for both Light and Dark Mode		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-538"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-536">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-537'
	>
	Shapes in Jetpack Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-541"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-539">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-540'
	>
	With shape customization, we want our composable content to have rounded corners. To do that, the best practice is to create the <strong><code>Shape.kt</code></strong> file and define shapes for small, medium and large components as follows:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-543"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">val </span><span class="token">Shapes </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">Shapes</span><span class="token">(
</span></span><span class="line"><span class="token">   small </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">RoundedCornerShape</span><span class="token">(</span><span class="token" style="color: #005cc5;">4</span><span class="token">.dp),
</span></span><span class="line"><span class="token">   medium </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">RoundedCornerShape</span><span class="token">(</span><span class="token" style="color: #005cc5;">8</span><span class="token">.dp),
</span></span><span class="line"><span class="token">   large </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">RoundedCornerShape</span><span class="token">(</span><span class="token" style="color: #005cc5;">16</span><span class="token">.dp)
</span></span><span class="line"><span class="token">)
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-546"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-544">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-545'
	>
	Inside the <strong><code>Theme.kt</code></strong> file, update <strong><code>InfinumComposeAppTheme</code></strong> with previously defined shapes attribute:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-548"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumComposeAppTheme</span><span class="token">(
</span></span><span class="line"><span class="token">   darkTheme</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Boolean</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">isSystemInDarkTheme</span><span class="token">(),
</span></span><span class="line"><span class="token">   content</span><span class="token">: </span><span class="token" style="color: #6f42c1;">@Composable</span><span class="token"> () </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> Unit
</span></span><span class="line"><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">   </span><span class="token">MaterialTheme</span><span class="token">(
</span></span><span class="line"><span class="token">       </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">       shapes </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Shapes
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-551"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-549">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-550'
	>
	Since shapes are used on the surface, not in the background, wrap <strong><code>Row</code></strong> composable inside the <strong><code>InfinumContent</code></strong> with <strong><code>Surface</code></strong> composable to get the effect:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-553"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun InfinumContent</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">Surface</span><span class="token">(shape </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MaterialTheme.shapes.large) {
</span></span><span class="line"><span class="token">       </span><span class="token">Row </span><span class="token">{
</span></span><span class="line"><span class="token">           </span><span class="token">Image</span><span class="token">(
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">           )
</span></span><span class="line"><span class="token">           </span><span class="token">Text</span><span class="token">(
</span></span><span class="line"><span class="token">               </span><span class="token" style="color: #d73a49;">..</span><span class="token">.
</span></span><span class="line"><span class="token">            )
</span></span><span class="line"><span class="token">       }
</span></span><span class="line"><span class="token">     }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-556"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-554"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-555">
	<picture class="image__picture block-media__image-picture">
								
			<source
				srcset=https://infinum.com/uploads/2021/04/jetpack-compose-framework-6-1400x959.webp				media='(max-width: 699px)'
				type=image/webp								height="959"
												width="1400"
				 />
												<img
					src="https://infinum.com/uploads/2021/04/jetpack-compose-framework-6.webp"
					class="image__img block-media__image-img"
					alt=""
										height="972"
															width="1419"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Preview with custom shapes for both Light and Dark Mode		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-559"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-557">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-558'
	>
	Ready to adopt? Jetpack Compose interoperability</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-562"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-560">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-561'
	>
	Jetpack Compose is interoperable with existing view-based UI. If you are building a new application from scratch, implementing a UI complete in Compose is the best option.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-565"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-563">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-564'
	>
	If you have an existing project and want to migrate to Jetpack Compose, it is a big step to migrate all at once. Instead, you can combine Compose with existing UI design implementation.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-568"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-566">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-567'
	>
	Compose in Android Views</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-571"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-569">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-570'
	>
	We already covered using Compose inside <strong><code>Activity</code></strong> in previous sections. To create an entire Compose-based UI, call <strong><code>setContent</code></strong> inside the <strong><code>onCreate</code></strong> method in <strong><code>Activity</code></strong> and pass whatever composable functions you like, like the following:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-573"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreate</span><span class="token">(savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?</span><span class="token">) {
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #005cc5;">super</span><span class="token">.onCreate</span><span class="token">(savedInstanceState)
</span></span><span class="line"><span class="token">   </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">val </span><span class="token">viewModel </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">viewModel</span><span class="token">(modelClass </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MainViewModel</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">.java)
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumHome</span><span class="token">(viewModel)
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-576"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-574">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-575'
	>
	When you want to use Compose functionalities in an existing <strong><code>Fragment</code></strong>, we need to add <strong><code>ComposeView</code></strong> inside the fragment layout and call <strong><code>setContent</code></strong> on that view. <strong><code>ComposeView</code></strong> is Android View that it is attached to <strong><code>LifecyleOwner</code></strong> like any other view.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-579"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-577">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-578'
	>
	Simply add <strong><code>ComposeView</code></strong> into XML layout:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-581"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">&lt;</span><span class="token">?xml version</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">1.0</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> encoding</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">utf-8</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">?</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">&lt;</span><span class="token">androidx.constraintlayout.widget.ConstraintLayout
</span></span><span class="line"><span class="token">   xmlns</span><span class="token">:</span><span class="token" style="color: #6f42c1;">android</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">http://schemas.android.com/apk/res/android</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">   xmlns</span><span class="token">:</span><span class="token" style="color: #6f42c1;">app</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">http://schemas.android.com/apk/res-auto</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">   android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">id</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">@+id/container</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">   android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_width</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">match_parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">   android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_height</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">match_parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token" style="color: #d73a49;">&lt;</span><span class="token">androidx.compose.ui.platform.ComposeView
</span></span><span class="line"><span class="token">       android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">id</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">@+id/composeView</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_width</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">0dp</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       android</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_height</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">0dp</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       app</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_constraintBottom_toBottomOf</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       app</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_constraintEnd_toEndOf</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       app</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_constraintStart_toStartOf</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">
</span></span><span class="line"><span class="token">       app</span><span class="token">:</span><span class="token" style="color: #6f42c1;">layout_constraintTop_toTopOf</span><span class="token" style="color: #d73a49;">=</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">parent</span><span class="token" style="color: #032f62;">&quot;</span><span class="token"> </span><span class="token" style="color: #d73a49;">/</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">&lt;</span><span class="token" style="color: #d73a49;">/</span><span class="token">androidx.constraintlayout.widget.ConstraintLayout</span><span class="token" style="color: #d73a49;">&gt;</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-584"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-582">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-583'
	>
	Inside the <strong><code>Fragment</code></strong> source code, inflate upper layout, find <strong><code>ComposeView</code></strong> and call <strong><code>setContent</code></strong> on it:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-586"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreateView</span><span class="token">(
</span></span><span class="line"><span class="token">   inflater</span><span class="token">: </span><span class="token" style="color: #6f42c1;">LayoutInflater</span><span class="token">,
</span></span><span class="line"><span class="token">   container</span><span class="token">: </span><span class="token" style="color: #6f42c1;">ViewGroup</span><span class="token">?</span><span class="token">,
</span></span><span class="line"><span class="token">   savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?
</span></span><span class="line"><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">View</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> inflater</span><span class="token">.inflate</span><span class="token">(
</span></span><span class="line"><span class="token">   R.layout.fragment_main, container, </span><span class="token" style="color: #005cc5;">false</span><span class="token">
</span></span><span class="line"><span class="token">)</span><span class="token">.apply </span><span class="token">{
</span></span><span class="line"><span class="token">   </span><span class="token">findViewById</span><span class="token">&lt;</span><span class="token" style="color: #6f42c1;">ComposeView</span><span class="token">&gt;</span><span class="token">(R.id.composeView)</span><span class="token">.setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">val </span><span class="token">viewModel </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">viewModel</span><span class="token">(modelClass </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MainViewModel</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">.java)
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumHome</span><span class="token">(viewModel)
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-589"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-587">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-588'
	>
	If you want to build the whole <strong><code>Fragment</code></strong> screen into Compose, you can directly pass <strong><code>ComposeView</code></strong> without needed for XML at all:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-591"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">override</span><span class="token"> </span><span class="token">fun onCreateView</span><span class="token">(
</span></span><span class="line"><span class="token">   inflater</span><span class="token">: </span><span class="token" style="color: #6f42c1;">LayoutInflater</span><span class="token">,
</span></span><span class="line"><span class="token">   container</span><span class="token">: </span><span class="token" style="color: #6f42c1;">ViewGroup</span><span class="token">?</span><span class="token">,
</span></span><span class="line"><span class="token">   savedInstanceState</span><span class="token">: </span><span class="token" style="color: #6f42c1;">Bundle</span><span class="token">?
</span></span><span class="line"><span class="token">)</span><span class="token">: </span><span class="token" style="color: #6f42c1;">View</span><span class="token"> </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">ComposeView</span><span class="token">(</span><span class="token">requireContext</span><span class="token">())</span><span class="token">.apply </span><span class="token">{
</span></span><span class="line"><span class="token">   </span><span class="token">setContent </span><span class="token">{
</span></span><span class="line"><span class="token">       </span><span class="token">val </span><span class="token">viewModel </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">viewModel</span><span class="token">(modelClass </span><span class="token" style="color: #d73a49;">=</span><span class="token"> MainViewModel</span><span class="token">::</span><span class="token" style="color: #6f42c1;">class</span><span class="token">.java)
</span></span><span class="line"><span class="token">       </span><span class="token">InfinumHome</span><span class="token">(viewModel)
</span></span><span class="line"><span class="token">   }
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-594"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-592">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-593'
	>
	Android Views in Compose</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-597"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-595">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-596'
	>
	Including existing Android Views in Jetpack Compose UI is also possible. This approach is handy when some components are unavailable in Compose like <strong><code>MapView</code></strong> or <strong><code>AdView</code></strong>. This approach is also applicable to already created custom views.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-600"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-598">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-599'
	>
	Implement the mentioned <strong><code>MapView</code></strong> in the Compose world like this:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-602"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-kotlin github-light" data-language="kotlin" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #6f42c1;">@Composable</span><span class="token">
</span></span><span class="line"><span class="token">fun ComposeMapView</span><span class="token">() {
</span></span><span class="line"><span class="token">   </span><span class="token">var </span><span class="token">googleMap</span><span class="token">: </span><span class="token" style="color: #6f42c1;">GoogleMap</span><span class="token">? </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token" style="color: #005cc5;">null</span><span class="token">
</span></span><span class="line"><span class="token">   </span><span class="token">AndroidView</span><span class="token">(
</span></span><span class="line"><span class="token">       modifier </span><span class="token" style="color: #d73a49;">=</span><span class="token"> Modifier</span><span class="token">.fillMaxSize</span><span class="token">(),
</span></span><span class="line"><span class="token">       factory </span><span class="token" style="color: #d73a49;">=</span><span class="token"> { context </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token">
</span></span><span class="line"><span class="token">           </span><span class="token">MapView</span><span class="token">(context)</span><span class="token">.apply </span><span class="token">{
</span></span><span class="line"><span class="token">               MapsInitializer</span><span class="token">.initialize</span><span class="token">(context)
</span></span><span class="line"><span class="token">               googleMap </span><span class="token" style="color: #d73a49;">=</span><span class="token"> </span><span class="token">awaitMap</span><span class="token">()
</span></span><span class="line"><span class="token">           }
</span></span><span class="line"><span class="token">       },
</span></span><span class="line"><span class="token">       update </span><span class="token" style="color: #d73a49;">=</span><span class="token"> { mapView </span><span class="token" style="color: #d73a49;">-&gt;</span><span class="token"> </span><span class="token" style="color: #6a737d;">/*</span><span class="token" style="color: #6a737d;"> do something with the MapView </span><span class="token" style="color: #6a737d;">*/</span><span class="token"> }
</span></span><span class="line"><span class="token">   )
</span></span><span class="line"><span class="token">}
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-605"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-603">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-604'
	>
	<strong><code>AndroidView</code></strong> is a composable function that shows existing Android components inside Compose UI. It took a modifier parameter for defining view attributes, factory function that will return the declared component (in the upper scenario MapView), and update the function invoked when the view is inflated. Showing <strong><code>MapView</code></strong> inside Compose UI is easy peasy.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-608"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-606">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-607'
	>
	Dig deeper into Jetpack Compose</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-611"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-609">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-610'
	>
	This article covered the declarative approach used by Compose, how to get started with Compose project, and how to create basic layouts. We also reviewed theming and how easily we can style our components and use a color palette depending on Light or Dark Mode. Finally, we explored Jetpack Compose interoperability and explained how to switch between regular view-based UI to Compose and vice versa.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-614"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-612">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-613'
	>
	A sequel to this blog post is in the making as we speak, in which we will dig deeper into Jetpack Compose, covering some more advanced aspects such as state management and composition, how to perform animations and make our UI more alive, as well as how to test our Compose layout. Stay tuned!</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/jetpack-compose-framework/">Android, Meet Jetpack Compose!</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>