<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Yan Falcao on Medium]]></title>
        <description><![CDATA[Stories by Yan Falcao on Medium]]></description>
        <link>https://medium.com/@yanfalcao10?source=rss-50d2ec8da66f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*cKmen2RrYAHznR34ZZT-Cw.jpeg</url>
            <title>Stories by Yan Falcao on Medium</title>
            <link>https://medium.com/@yanfalcao10?source=rss-50d2ec8da66f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 16 May 2026 17:26:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@yanfalcao10/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Github Copilot Keyboard Shortcuts in Android Studio]]></title>
            <link>https://medium.com/@yanfalcao10/github-copilot-keyboard-shortcuts-in-android-studio-62dbe639d7c8?source=rss-50d2ec8da66f------2</link>
            <guid isPermaLink="false">https://medium.com/p/62dbe639d7c8</guid>
            <category><![CDATA[shortcuts]]></category>
            <category><![CDATA[android-studio]]></category>
            <category><![CDATA[github-copilot]]></category>
            <category><![CDATA[mac]]></category>
            <category><![CDATA[windows]]></category>
            <dc:creator><![CDATA[Yan Falcao]]></dc:creator>
            <pubDate>Tue, 30 Sep 2025 20:27:21 GMT</pubDate>
            <atom:updated>2025-09-30T20:27:21.206Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/784/1*YTUaACxR0NdT4qeRQUPj-A.png" /></figure><p>As Android developers, we’re look for ways to streamline our workflow and increase productivity. While we were not constantly always aware of every new tool or shortcut. Minding this I&#39;m here to share some shortcuts I&#39;ve recently learned from an online presenting in my workplace, and others that I already knew.</p><p>Integrating tools like Github Copilot into Android Studio can significantly speed up coding. However, certain situations can reduce this efficiency or be frustrating. This article will walk you through some essential commands.</p><h3>The Shortcuts</h3><p>Here are the keyboard shortcuts you need to know to take control of Github Copilot in Android Studio:</p><h4><strong>Accept an inline suggestion</strong></h4><p>Let&#39;s begin with the basic shortcut for quickly accepting a full, completed suggestion from Copilot.</p><p><strong>Mac &amp; Windows:</strong> Tab</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FknhQbnQVxf8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DknhQbnQVxf8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FknhQbnQVxf8%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/4ce894ac2536e4944fd7df6d82f96acb/href">https://medium.com/media/4ce894ac2536e4944fd7df6d82f96acb/href</a></iframe><h4>Accept <strong>next word of</strong> an inline suggestion</h4><p>Next one I&#39;ve recently found, sometimes I don&#39;t want to accept the whole suggestion, just the first words and adapt the rest. When Copilot suggests multiple words, using this shortcut you&#39;re able to accept only the next word at time, giving you more control over the final code.</p><p><strong>Mac:</strong> Command + →</p><p><strong>Windows:</strong> Ctrl + →</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FFpYf6Da9XQo%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DFpYf6Da9XQo&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FFpYf6Da9XQo%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/33dd285eed73a3fe7e583b77c003520f/href">https://medium.com/media/33dd285eed73a3fe7e583b77c003520f/href</a></iframe><h4>Show next and previus inline suggestion</h4><p>Sometimes Copilot offers multiple suggestions. Use this shortcut to cycle through them until you find the one that best fits your needs.</p><p><strong>Mac:</strong> Option (⌥) + ] (next suggestion) and Option (⌥) + [ (previous suggestion)</p><p><strong>Windows:</strong> Alt + ] (next suggestion) and Alt + [ (previous suggestion)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F3EI_ygDeDSY%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D3EI_ygDeDSY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F3EI_ygDeDSY%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/41c314bbd31c77d111dd7e55457ff235/href">https://medium.com/media/41c314bbd31c77d111dd7e55457ff235/href</a></iframe><h4><strong>Trigger</strong> inline suggestion</h4><p>Sometimes Copilot doesn&#39;t provide a suggestion, but you want to explicitly ask for one. This shortcut manually triggers the suggestion, even if you haven’t started typing.</p><p><strong>Mac:</strong> Option (⌥) + \</p><p><strong>Windows:</strong> Alt + \</p><iframe src="https://cdn.embedly.com/widgets/media.html?url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DCvIE2xdWACM&amp;type=text%2Fhtml&amp;schema=youtube&amp;display_name=YouTube&amp;src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FCvIE2xdWACM%3Ffeature%3Doembed" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/8cc7426f1ab2afa550f9a8e434993a45/href">https://medium.com/media/8cc7426f1ab2afa550f9a8e434993a45/href</a></iframe><h4>Dismiss an inline suggestion</h4><p>The last one is simple but really helpful, because suggestions can be annoying, specially if Copilot is giving all wrong suggestions and you want do develop your own code. This command quickly gets it out of your way .</p><p><strong>Mac &amp; Windows:</strong> Esc</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FTTKiSvDWYUo%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DTTKiSvDWYUo&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FTTKiSvDWYUo%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/a090618393f1e6b75be42d23552ce45a/href">https://medium.com/media/a090618393f1e6b75be42d23552ce45a/href</a></iframe><h4>Conclusion</h4><p>Mastering these shortcuts will allow you to navigate through Copilot’s suggestions effortlessly, making it a seamless extension of your development process.</p><p>If Compose and Accessibility are interesting themes to you, take a look at the following articles:</p><ul><li><a href="https://medium.com/@yanfalcao10/text-scaling-for-a-better-user-experience-in-jetpack-compose-b9c7241eb4af">Text Scaling for a Better User Experience in Jetpack Compose</a></li><li><a href="https://medium.com/@yanfalcao10/4-common-talkback-issues-in-android-compose-c6e3c3d92d19">4 Common TalkBack Issues in Android Compose</a></li><li><a href="https://medium.com/@yanfalcao10/accessible-contrast-in-apps-with-jetpack-compose-442bdec98e9b">Accessible Contrast in Apps with Jetpack Compose</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=62dbe639d7c8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[4 Common TalkBack Issues in Android Compose]]></title>
            <link>https://medium.com/@yanfalcao10/4-common-talkback-issues-in-android-compose-c6e3c3d92d19?source=rss-50d2ec8da66f------2</link>
            <guid isPermaLink="false">https://medium.com/p/c6e3c3d92d19</guid>
            <category><![CDATA[jetpack-compose]]></category>
            <category><![CDATA[accessibility-design]]></category>
            <category><![CDATA[talkback]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[user-experience]]></category>
            <dc:creator><![CDATA[Yan Falcao]]></dc:creator>
            <pubDate>Thu, 13 Feb 2025 20:29:05 GMT</pubDate>
            <atom:updated>2025-07-05T21:10:08.390Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*MQtbVMaqQgucTPzJ4I8oEw.png" /></figure><p>While studying accessibility in Jetpack Compose, I encountered some issues while making my app more supportive of Talkback. In this article, we&#39;ll explore strategies to improve accessibilty in your app.</p><p>This article does not cover all possible scenarios and assume you already have a basic understanding of Talkback.</p><p>A companion Github repository with sample code is available <a href="https://github.com/yanfalcao/TalkBackTips">here</a>. You can check it out and run the demo app on your device to experience the issues and try the solutions yourself.</p><h4>1. Grouping composables</h4><p>Often, the system automatically merges certain composables, such as the contents of a list item or any clickable container, treating them as a single element for accessibility purposes. However, there are cases where we need to manually merge composables to improve selection behavior and make navigation smoother for TalkBack users.</p><p><strong>Example</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nj59-n2Kf0_slVJOz3eJ7w.png" /></figure><p>The examples above show the difference between merged and unmerged composables. Proper grouping improves the listening experience and enhances the app’s overall accessibility.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/66d0575861385899bdc8c823069f496a/href">https://medium.com/media/66d0575861385899bdc8c823069f496a/href</a></iframe><p>In this example, all Text elements are wrapped in a parent composable. To merge them into a single accessibility node, we use the mergeDescendants property in the parent’s Modifier. You can see this on <strong>line 12</strong>. Now, when selected, the elements are read as a single unit instead of individually.</p><h4>2. Making TextFields More Informative</h4><p>This is more of an accessibility best practice than a direct issue. When using TextField, always provide a label because TalkBack will read your label when the user touches the input field.</p><p>However, in forms with multiple TextFields, each field serves a different purpose, requiring users to enter specific data. While the title above the field helps, it’s far more informative if users can instantly identify the field they are interacting with through TalkBack.</p><p>A great way to enhance accessibility is by setting a contentDescription for the label, not the TextField itself. If you apply the contentDescription directly to the TextField, TalkBack will read both the label and the description, creating redundancy.</p><p><strong>Example</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v0CwhmKRMaXkiN73CwbFuA.png" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c9009d5d6c5e53eef44268403aca355d/href">https://medium.com/media/c9009d5d6c5e53eef44268403aca355d/href</a></iframe><ol><li><strong>Define a</strong> contentDescription <em>(line 4) — </em>Instead of just saying <em>“Type here”</em>, TalkBack will read <em>“Enter your first name”</em>, making it <strong>more meaningful</strong>.</li><li><strong>Add the semantics in the label</strong> <em>(line 25–27)</em> — We use semantics {} to define the new description.</li></ol><h4>3. Update state changes</h4><p>Sometimes, simply adding a contentDescription isn&#39;t enough. If your elements have a state, it&#39;s important to ensure that TalkBack users can understand which state they are in.</p><p><strong>Example</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y0DnpPpMj9rwa19ll1ZjqA.png" /></figure><p>In the image above, the <strong>favorite button</strong> changes when selected, but TalkBack users won’t know whether it’s currently <strong>selected or unselected</strong> — they will only hear <em>“Favorite. Button”</em>, without any indication of state.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9775a55edad9392a408f162c77ee98de/href">https://medium.com/media/9775a55edad9392a408f162c77ee98de/href</a></iframe><p><strong>Solution</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3tjw4PGEOjBCM2gIfENDUQ.png" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7812ed914c072ff682ec31ae9a9d6232/href">https://medium.com/media/7812ed914c072ff682ec31ae9a9d6232/href</a></iframe><p>To fix this, we need to explicitly communicate the state to TalkBack. Instead of using IconButton, we should use <strong>IconToggleButton</strong>, which automatically provides the state (checked or not checked) to accessibility services.</p><h4>4. Custom Actions</h4><p>In many apps, a single component may have <strong>multiple actions</strong>. For example, a <strong>list item</strong> could have a favorite button, swipe to delete and/or archive and potentially even more actions.</p><p><strong>Problem</strong></p><p>When TalkBack is enabled, execute all this actions can be difficult. Adding them through custom touch gestures isn’t always effective, and if you include all actions in the TalkBack description, it becomes too long and confusing.</p><p><strong>Solution</strong></p><p>To improve accessibility, TalkBack provides a built-in menu where you can define Custom Actions. Instead of overloading the user with long descriptions, these actions appear in the TalkBack Actions Menu, making them easier to access.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/324/1*lpg56ABrbZViY1J3_urnpw.gif" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5f3114e0ee66a3ee8d0b1acc0e5eb255/href">https://medium.com/media/5f3114e0ee66a3ee8d0b1acc0e5eb255/href</a></iframe><p><strong>How This Works:</strong></p><ol><li><strong>Define the action label</strong> <em>(Line 4–8)</em> — The label changes dynamically depending on whether the item is favorited or not.</li><li><strong>Add a semantics modifier</strong> <em>(Line 16–27)</em> — We use customActions inside semantics {} to define the <strong>custom TalkBack action</strong>.</li><li><strong>Clear semantics from the favorite button</strong> <em>(Line 33)</em> – Since we want the action only in the TalkBack menu, we use .clearAndSetSemantics().</li></ol><h4>Conclusion</h4><p>Improving accessibility in Jetpack Compose is not just about adding contentDescription to UI elements—it’s about ensuring that all users, including those relying on TalkBack, have a smooth and intuitive experience.</p><p>Accessibility isn&#39;t just an optional feature—it’s a fundamental part of building <strong>high-quality apps</strong>. Start small, test with TalkBack, and keep refining your app’s accessibility to ensure <strong>everyone</strong> can use it with ease.</p><p>If you found this guide helpful, share it with other developers and let me know in the comments if you’ve encountered other accessibility challenges in Jetpack Compose!</p><p>Connect with me on <a href="https://www.linkedin.com/in/yan-santos-falcao/">LinkedIn</a>!</p><p>If you liked this article, <strong>Clap</strong> it to reach more people.</p><h4>References</h4><ul><li><a href="https://developer.android.com/develop/ui/compose/quick-guides/content/video/accessibility-in-compose">Accessibility in Compose | Jetpack Compose | Android Developers</a></li><li><a href="https://medium.com/microsoft-mobile-engineering/android-accessibility-resolving-common-talkback-issues-3c45076bcdf6">Android Accessibility — Resolving common Talkback issues</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6e3c3d92d19" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Accessible Contrast in Apps with Jetpack Compose]]></title>
            <link>https://medium.com/@yanfalcao10/accessible-contrast-in-apps-with-jetpack-compose-442bdec98e9b?source=rss-50d2ec8da66f------2</link>
            <guid isPermaLink="false">https://medium.com/p/442bdec98e9b</guid>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[user-experience]]></category>
            <category><![CDATA[jetpack-compose]]></category>
            <category><![CDATA[contrast]]></category>
            <dc:creator><![CDATA[Yan Falcao]]></dc:creator>
            <pubDate>Mon, 30 Dec 2024 14:55:28 GMT</pubDate>
            <atom:updated>2025-07-05T21:09:47.226Z</atom:updated>
            <content:encoded><![CDATA[<p>In this article, I’ll address three key questions: What is color contrast? Who benefits from contrast? How can you test it in your Compose app?</p><h4>What is color contrast?</h4><p>According to Google, a “contrast ratio” is a measure of the difference in luminance — or intensity of light emitted — between two adjacent colors displayed on a screen. This ratio ranges from 1 to 21 (often written as 1:1 to 21:1), with higher numbers indicating greater contrast.</p><p>The Web Content Accessibility Guidelines (WCAG) recommend the following minimum and enhanced contrast ratios:</p><p>According to Google, “contrast ratio” is a computation of the difference in luminance, or intensity of light emitted, between two neighboring colors when shown on a display. This ratio ranges from 1 to 21 (often written as 1:1 to 21:1), where increasing numbers mean higher contrast.</p><p>The Web Content Accessibility Guidelines (WCAG) recommend the following <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html">minimum</a> and <a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html">enhanced</a> contrast ratios:</p><p><strong>Minimum Contrast (WCAG Level AA):</strong></p><ul><li>At least 4.5<strong>:</strong>1 for small text (below 18 point regular or 14 point bold)</li><li>At least 3.0<strong>:</strong>1 for large text (18 point and above regular or 14 point and above bold)</li></ul><p><strong>Enhanced Contrast (WCAG Level AAA):</strong></p><ul><li>7.1:1 for small text (below 18 point regular or 14 point bold)</li><li>4.5<strong>:</strong>1 for large text (18 point and above regular or 14 point and above bold)</li></ul><h4>Who Benefits from Proper Color Contrast?</h4><p>People with <a href="https://www.aoa.org/healthy-eyes/eye-and-vision-conditions/color-vision-deficiency?sso=y">color-vision deficiency</a>, commonly referred to as “color blindness”, is the inability to distinguish certain shades of color. Around 12% of men and a smaller percentage of women have some form of color vision deficiency.</p><p>Approximately 4% of the population has low vision, whereas 0.6% are blind. Low-vision conditions that increase with age, because age-related eye diseases, such as <a href="https://www.hopkinsmedicine.org/healthlibrary/conditions/adult/eye_care/age-related_macular_degeneration_amd_85,p00509">age-related macular degeneration </a>, <a href="https://www.hopkinsmedicine.org/healthlibrary/conditions/adult/eye_care/glaucoma_85,p00504">glaucoma </a>and <a href="https://www.hopkinsmedicine.org/healthlibrary/conditions/adult/eye_care/diabetic_retinopathy_85,p00497">diabetic retinopathy </a>, most often cause it. At the age of 45, less than 1%of people are likely to have low vision, but by the age of 75, that jumps to almost 5%, and then to 15% by the age of 85.</p><h4>Let&#39;s see some examples</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FuB4GMEVLuOlAjMe.jpg" /></figure><p>Above are some color contrast examples. To exemplify the theme I&#39;ll use a screen of my recipe app, I’ve exaggerated the contrasts to highlight the issue:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*42Z7tMI515XEvQovi8JgQw.png" /><figcaption>enhanced contrast — minimum contrast — low contrast</figcaption></figure><p>Above we can see the same screen with different contrast the first one is the level AAA, the second is the level AA and the last is with low contrast. Just these images exemplify the point of this article.</p><p>Below I get the same image and applied a <a href="https://chromewebstore.google.com/detail/funkify-%E2%80%93-disability-simu/ojcijjdchelkddboickefhnbdpeajdjg">filter to simulate lowered vision</a> in aged people.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*odiRHJ0xLl4vCv1gKP8yrA.png" /><figcaption>Lowered vision</figcaption></figure><p>The eye problems with contrast are huge, but I focused in the common one, the aged degeneration of the vision. The intension here is try to give a visual parameter to help you to imagine yourself in these situations.</p><h4>How to test</h4><p>Jetpack Compose provides an easy way to test the accessibility of your screens using the <strong>Compose UI Check</strong> feature in the screen preview. The UI Check automatically audits your Compose UI for accessibility issues. Android Studio flags issues such as stretched text on large screens or low color contrast in the Problems panel.</p><p>Jetpack Compose provides an easy way to test the accessibility of your screens using the <a href="https://developer.android.com/guide/topics/ui/accessibility/testing">Compose UI Check</a> in your screen preview. The UI Check automatically audits your Compose UI for accessibility issues. Android Studio checks that your UI works across different screen sizes by highlighting issues such as text stretched on large screens or low color contrast in the problems panel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P-vVY1IgKAjuYAjXQ64bPQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*26nZvNhrsiLXhhyoheTUww.png" /></figure><h4>How to improve your contrast</h4><p>If your UI fails the contrast check or if you’re prototyping and unsure about color combinations, tools like <a href="https://color.adobe.com/pt/create/color-contrast-analyzer"><strong>Adobe Color</strong></a><strong> </strong>can help. On their website, you can input your text and background colors to:</p><ul><li>Determine the contrast ratio.</li><li>Check if the colors pass or fail accessibility standards.</li><li>Get suggestions for better color combinations to improve contrast.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Mg_PcGBZFHFip6uAk3fnRQ.png" /></figure><h4>Final Thoughts</h4><p>Designing with accessibility in mind ensures your app is usable by a broader audience, including those with visual impairments. Test your UI, adjust your colors, and make your app inclusive for everyone.</p><p>Leave a comment, give a like and connect with me on <a href="https://www.linkedin.com/in/yan-santos-falcao/">LinkedIn</a>!</p><p>If you liked this article, <strong>Clap</strong> it to reach more people.</p><h4>References</h4><ul><li><a href="https://www.smashingmagazine.com/2014/10/color-contrast-tips-and-tools-for-accessibility/">Color Contrast And Why You Should Rethink It - Smashing Magazine</a></li><li><a href="https://www.netguru.com/blog/accessibility-more-than-contrast">Accessibility Is So Much More Than Contrast</a></li></ul><p><a href="https://color.adobe.com/pt/create/color-contrast-analyzer">https://color.adobe.com/pt/create/color-contrast-analyzer</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=442bdec98e9b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Previewing Composable with Different Window Sizes]]></title>
            <link>https://medium.com/@yanfalcao10/jetpack-compose-technique-for-previewing-composable-with-different-window-sizes-db0f368b646a?source=rss-50d2ec8da66f------2</link>
            <guid isPermaLink="false">https://medium.com/p/db0f368b646a</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[user-experience]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[jetpack-compose]]></category>
            <category><![CDATA[preview]]></category>
            <dc:creator><![CDATA[Yan Falcao]]></dc:creator>
            <pubDate>Mon, 28 Oct 2024 20:30:13 GMT</pubDate>
            <atom:updated>2025-07-05T21:09:25.539Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pufEZjUtqH83Q3tlM-keqQ.png" /></figure><p>While studying responsive design with Jetpack Compose, I came across a new feature recommended by Google to assist in designing, developing, and testing adaptable layouts: <strong>Window Size Classes</strong>. This feature, detailed in the <a href="https://developer.android.com/develop/ui/compose/layouts/adaptive/use-window-size-classes#test_window_size_classes">Android Documentation</a>, helps organize layout elements across different screen sizes for a more consistent and accessible UI. Here’s how Android describes it:</p><blockquote>Window size classes categorize the display area available to your app as <em>compact</em>, <em>medium</em>, or <em>expanded</em>. Available width and height are classified separately, so at any point in time, your app has two window size classes — one for width, one for height. Available width is usually more important than available height due to the ubiquity of vertical scrolling, so the width window size class is likely more relevant to your app’s UI.</blockquote><h4>Explaining the problem</h4><p>When trying to preview composables with Window Size Classes, I faced an issue: every preview was treated as a compact screen, regardless of its width or height setting. Here’s an example:</p><pre>import androidx.compose.foundation.background<br>import androidx.compose.foundation.layout.Box<br>import androidx.compose.foundation.layout.fillMaxSize<br>import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo<br>import androidx.compose.runtime.Composable<br>import androidx.compose.ui.Modifier<br>import androidx.compose.ui.graphics.Color<br>import androidx.compose.ui.tooling.preview.PreviewScreenSizes<br>import androidx.window.core.layout.WindowHeightSizeClass<br>import androidx.window.core.layout.WindowSizeClass<br><br>@Composable<br>fun BackgroundExample(windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass) {<br>    val backgroundColor =<br>        when (windowSizeClass.windowHeightSizeClass) {<br>            WindowHeightSizeClass.COMPACT -&gt; Color.Red<br>            WindowHeightSizeClass.MEDIUM -&gt; Color.Green<br>            else -&gt; Color.Blue<br>        }<br><br>    Box(modifier = Modifier<br>        .fillMaxSize()<br>        .background(backgroundColor)<br>    )<br>}<br><br>@Composable<br>@PreviewScreenSizes<br>fun PreviewExample() {<br>    BackgroundExample()<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j5Ke00DYAgcxkSqLKDoXJQ.png" /><figcaption>Desktop — Phone — Landscape Phone — Tablet — Unfolded Foldable</figcaption></figure><p>Despite @PreviewScreenSizesspecify different screen sizes — Desktop, Phone, Landscape Phone, Tablet, and Foldable — the Window Size Classes still registered everything as compact. This bug means you can’t test accurately across screen types.</p><p>To address this issue, I found out a workaround. However, before implementing it, be sure to test without this solution, as Android may have resolved this bug in newer versions. If the issue persists, here’s the fix.</p><h4>Exploring Solution</h4><pre>@Composable<br>fun BackgroundExample(windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass) {<br>    ...<br>}<br><br>@Composable<br>@PreviewScreenSizes<br>fun PreviewExample() {<br>    val configuration = LocalConfiguration.current<br>    val windowSizeClass = WindowSizeClass.compute(<br>        dpHeight = configuration.screenHeightDp.toFloat(),<br>        dpWidth = configuration.screenWidthDp.toFloat(),<br>    )<br><br>    BackgroundExample(windowSizeClass)<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2tAGd2sXBR-0t9Z3GRX8eQ.png" /><figcaption>Desktop — Phone — Landscape Phone — Tablet — Unfolded Foldable</figcaption></figure><p>This approach uses LocalConfiguration to fetch the screen&#39;s width and height, which are then used to compute the WindowSizeClass. By directly passing these parameters, you can test how your composables behave across various screen types and improve responsiveness.</p><p>Leave a comment, give a like and connect with me on <a href="https://www.linkedin.com/in/yan-santos-falcao/">LinkedIn</a>.</p><p>If you liked this article, <strong>Clap</strong> it to reach more people.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=db0f368b646a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Text Scaling for a Better User Experience in Jetpack Compose]]></title>
            <link>https://medium.com/@yanfalcao10/text-scaling-for-a-better-user-experience-in-jetpack-compose-b9c7241eb4af?source=rss-50d2ec8da66f------2</link>
            <guid isPermaLink="false">https://medium.com/p/b9c7241eb4af</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[compose]]></category>
            <category><![CDATA[accessibility]]></category>
            <category><![CDATA[user-experience]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Yan Falcao]]></dc:creator>
            <pubDate>Wed, 23 Oct 2024 15:05:35 GMT</pubDate>
            <atom:updated>2025-07-05T21:08:40.672Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/810/1*wGjWoIRNrIZeYRDPSPxj3g.png" /></figure><p><strong>Font scale accessibility</strong> in mobile phones allows users to adjust the size of text displayed on their screens, making it easier for them to read content comfortably, regardless of their vision abilities. This feature is especially important for those with visual impairments, older adults, or anyone who prefers a larger text size for better readability.</p><p>In fact, a <a href="https://appt.org/en/stats">survey was made in the Netherlands</a> revealed that almost half of mobile phone users take advantage of accessibility features, with 24% of iOS and Android users opting to increase their font size.</p><p>In this article, I’ll walk you through some of the common challenges developers face when it comes to text scaling. But before diving into those issues, let’s see how to preview text scale in your code.</p><h3>How to preview</h3><p>In Jetpack Compose, you can do this easily by using the @PreviewFontScale annotation, available with the androidx.compose.ui:ui-tooling-preview-android library version 1.7.4 or newer.</p><pre>@PreviewFontScale<br>@Composable<br>fun ScalableTextPreview() {<br>    ...<br>}</pre><p>Alternatively, you can directly adjust the fontScale parameter within the @Previewannotation.</p><pre>@Preview(fontScale = 0.85f, name = &quot;Scale 85%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 1f, name = &quot;Scale 100%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 1.15f, name = &quot;Scale 115%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 1.3f, name = &quot;Scale 130%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 1.5f, name = &quot;Scale 150%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 1.8f, name = &quot;Scale 180%&quot;, group = &quot;Font Scaling&quot;)<br>@Preview(fontScale = 2f, name = &quot;Scale 200%&quot;, group = &quot;Font Scaling&quot;)<br>fun ScalableTextPreview() {<br>    ...<br>}</pre><h3>Problem 1: Text Overflow or Clipping</h3><p>One of the most common issues when dealing with font scaling is text overflow or clipping, which can degrade the user experience. Let’s look at an example in Jetpack Compose:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e7679ab413bb4b3fe6298822281bb98/href">https://medium.com/media/7e7679ab413bb4b3fe6298822281bb98/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/723/1*_l51GpSm8ma6el2uDJSXLw.png" /></figure><h4><strong>What’s wrong?</strong></h4><p>In this example, the Box has a fixed width of 100.dp and a height of 50.dp, while the Text component inside it contains a long string that overflow beyond the boundaries of the Box, leading to clipping and making the content unreadable.</p><h4>Solution:</h4><p>Here, we make adjustments to handle text scaling properly by removing Modifier.height and allowing the Box to resize dynamically.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f5702d33c5b7c5a1a3ff7cdc95de79d1/href">https://medium.com/media/f5702d33c5b7c5a1a3ff7cdc95de79d1/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/707/1*yxOGNeQxTj3_vTuw_EEl6g.png" /></figure><h3>Problem 2: Hidden Content in Grid View</h3><p>When building a grid layout, it’s common to use fixed sizes to achieve a perfect form, often inspired by a particular design. While this can work well with some font scales, it may fail with others, leading to hidden content. This is especially problematic in Grid Views that display important information or provide access to essential features. Let’s look at an example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ee1239a9512c5252e9eef411590998e3/href">https://medium.com/media/ee1239a9512c5252e9eef411590998e3/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/863/1*FTM0QwMRVNWm10kqJPIp2Q.png" /></figure><h4>What’s wrong?</h4><p>In this example, the fixed size of 120.dp for each grid tile works well when the font size is at 100% scale, but as the user increases the font size, content may get cut off or overlap, making some text unreadable. This can lead to a poor user experience, especially if the grid is meant to display critical information like emergency contacts.</p><h4>Solution: Using Modifier.sizeIn()</h4><p>To keep the square format of the grid tiles in 100% scale while ensuring that text remains readable, we can use Modifier.sizeIn(). This property is useful to constrain the width of the content to be between minWidth dp and maxWidth dp and the height of the content to be between minHeight dp and maxHeight dp, constraining it to a minimum width and height while adapting when the text needs more space.</p><p>By specifying just minWidth and minHeight, we maintain the tile&#39;s shape at standard scales, and when the text grows larger, the Surface adjusts automatically, preventing clipping. Here’s the adjusted code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f420d67107c1117d642badd923e16ef1/href">https://medium.com/media/f420d67107c1117d642badd923e16ef1/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/864/1*ODmDxbe6TA3abNyITN8EIw.png" /></figure><h3>Problem 3: Secondary Texts Taking Up Much Space</h3><p>The third common problem when handling font scaling is not text overlapping but rather text taking up more space than intended. In this case, the text adapts correctly to larger font sizes, but secondary texts, such as subtitles, can start consuming a lot of screen space — especially in list views. Since these texts are not primary content, it’s often better to limit how much of them is displayed. Let’s look at an example of this issue:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f6715a93ff896392a46f680c6dd93fcd/href">https://medium.com/media/f6715a93ff896392a46f680c6dd93fcd/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cqE1iIo9d1GEDkh_agWc6g.png" /></figure><h4>What’s wrong?</h4><p>In this example, everything looks fine when the system font scale is at 100%, but as soon as it increases to 150%, the subtitle text starts to take up more space, making each list item much larger than it needs to be. This can result in a cluttered and inefficient use of screen space.</p><h4>Solution: Using Modifier.heightIn</h4><p>To address this issue, we can use Modifier.heightIn() to set a maximum height for each list item, ensuring that even with larger text sizes, the list item doesn&#39;t expand excessively. This works similarly to Modifier.sizeIn(), but focuses only on height:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c841293f71ee8c382d3345f14b897a2/href">https://medium.com/media/4c841293f71ee8c382d3345f14b897a2/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xFMirt-srGr37jp9vyaCgg.png" /></figure><p>By defining a maximum height, we prevent the list item from growing too large. However, this alone can lead to text being clipped if it exceeds the space available.</p><h4>Adding maxLines and TextOverflow.Ellipsis</h4><p>To ensure that text remains readable without overlapping or clipping, we can use the maxLines property along with TextOverflow.Ellipsis for the Text component. This allows us to limit the number of displayed lines and automatically add an ellipsis (...) if the text is too long. Here’s the complete solution:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e20f257c519545e1d49bbb36ac313f13/href">https://medium.com/media/e20f257c519545e1d49bbb36ac313f13/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*voAqYJbGc9xYnAjreO1jBw.png" /></figure><p>This approach is especially useful when dealing with dynamic text, where the length of the content is unpredictable. By limiting the number of lines and applying an ellipsis, you can ensure a consistent and user-friendly design, even when the text size of the list items varies.</p><h3>Conclusion</h3><p>Building accessible and responsive mobile apps requires careful attention to how text scales across different devices and user settings. While a 200% font scale might not always preserve the original design aesthetics, what truly matters is maintaining the usability and readability of the interface.</p><p>The inspiration for this post came from a LinkedIn story where a daughter noticed her father struggling to use a banking app with an interface that had become nearly impossible to understand due to larger font settings. You might think such situations are rare, but I’ve taken two of the situations in a banking app from one of the largest private banks in Brazil, a bank with over 2 trillion in assets. Despite its resources, the app’s interface became completely broken when the font size was increased.</p><p>So, here’s a challenge for you: grab your parents’ phone, set the font size to its maximum in the settings, and see if they can still navigate and use their apps effectively. It’s a simple test that can reveal a lot about the real-world accessibility of our designs. Making these adjustments might seem small, but they can significantly improve the experience for users who rely on these features every day.</p><p>Connect with me on <a href="https://www.linkedin.com/in/yan-santos-falcao/">LinkedIn</a><br>If you liked this article, <strong>Clap</strong> it to reach more people.</p><p><a href="https://www.linkedin.com/posts/biancacorreia_voc%C3%AAs-j%C3%A1-se-colocaram-no-lugar-de-uma-pessoa-ugcPost-7192012538996310016-hsM_?utm_source=share&amp;utm_medium=member_desktop">Bianca Correia on LinkedIn: Vocês já se colocaram no lugar de uma pessoa idosa? Esse é o print de um... | 239 comments</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b9c7241eb4af" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>