{"id":346759,"date":"2025-08-13T13:57:01","date_gmt":"2025-08-13T18:57:01","guid":{"rendered":"https:\/\/michigandigitalnews.com\/index.php\/2025\/08\/13\/whats-new-in-the-jetpack-compose-august-25-release\/"},"modified":"2025-08-13T13:57:01","modified_gmt":"2025-08-13T18:57:01","slug":"whats-new-in-the-jetpack-compose-august-25-release","status":"publish","type":"post","link":"https:\/\/michigandigitalnews.com\/index.php\/2025\/08\/13\/whats-new-in-the-jetpack-compose-august-25-release\/","title":{"rendered":"What\u2019s new in the Jetpack Compose August \u201925 release"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<meta content=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEgRQ1jqjKgegNQIov75-nK2IxHnoFNyHqFQK__P5EeK3NR8UX-Ninf_dPE_2Qm_JKzjrosNN5tW-4HFqerJIqCakaZ0bxy3MJbUH695NiLb_D1viAoxmuOcVU1C6bn3hc008BR1ZMAp_i63EZSMy7UcqlFh5TJo-ANYKcJBTN4mE_yG3GZut0OW2eUCPnc\/s1600\/Jetpack%20Compose%201%20-%20Metadata.png\" name=\"twitter:image\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEgRQ1jqjKgegNQIov75-nK2IxHnoFNyHqFQK__P5EeK3NR8UX-Ninf_dPE_2Qm_JKzjrosNN5tW-4HFqerJIqCakaZ0bxy3MJbUH695NiLb_D1viAoxmuOcVU1C6bn3hc008BR1ZMAp_i63EZSMy7UcqlFh5TJo-ANYKcJBTN4mE_yG3GZut0OW2eUCPnc\/s1600\/Jetpack%20Compose%201%20-%20Metadata.png\" style=\"display: none;\"\/><\/p>\n<p><em>Posted by Meghan Mehta \u2013 Developer Relations Engineer and Nick Butcher \u2013 Product Manager<\/em><\/p>\n<p><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjydwozpgYhFJnWocHWrgtMq5MS5_mKL6ieqbl3eDhsPFhrz5wv8jNxwxQ9Vfw3KW956caLKtrXeO7k4b2JTczwfNx3BNZrg1KsPCtt3Ti2GdR8CMGemYoYTDBHj3obpIcs3fE4UNWJX8A3KSofYw0dNAgRjquxwnQdOB21XE9nlANzmijSKHkW0w9k72w\/s1600\/Jetpack%20Compose%201.png\"><img decoding=\"async\" border=\"0\" data-original-height=\"800\" data-original-width=\"100%\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjydwozpgYhFJnWocHWrgtMq5MS5_mKL6ieqbl3eDhsPFhrz5wv8jNxwxQ9Vfw3KW956caLKtrXeO7k4b2JTczwfNx3BNZrg1KsPCtt3Ti2GdR8CMGemYoYTDBHj3obpIcs3fE4UNWJX8A3KSofYw0dNAgRjquxwnQdOB21XE9nlANzmijSKHkW0w9k72w\/s1600\/Jetpack%20Compose%201.png\"\/><\/a><\/p>\n<p>Today, the <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/compose\" target=\"_blank\" rel=\"noopener\">Jetpack Compose August \u201825 release<\/a> is stable. This release contains version 1.9 of core compose modules (see the full <a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/bom\/bom-mapping\" target=\"_blank\" rel=\"noopener\">BOM mapping<\/a>), introducing new APIs for rendering shadows, 2D scrolling, rich styling of text transformations, improved list performance, and more!<\/p>\n<p>To use today\u2019s release, upgrade your <a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/bom\" target=\"_blank\" rel=\"noopener\">Compose BOM<\/a> version to 2025.08.00:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/>implementation(platform(<span style=\"color: #ba2121;\">\"androidx.compose:compose-bom:2025.08.00\"<\/span>))\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">Shadows<\/span><\/h2>\n<p>We&#8217;re happy to introduce two highly requested modifiers: <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.dropShadow%28androidx.compose.ui.graphics.Shape,kotlin.Function1%29\" target=\"_blank\" rel=\"noopener\">Modifier.dropShadow()<\/a><\/span> and <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.innerShadow%28androidx.compose.ui.graphics.Shape,kotlin.Function1%29\" target=\"_blank\" rel=\"noopener\">Modifier.innerShadow()<\/a><\/span> allowing you to render box-shadow effects (compared to the existing <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.shadow%28androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Shape,kotlin.Boolean,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color%29\" target=\"_blank\" rel=\"noopener\">Modifier.shadow()<\/a><\/span> which renders elevation based shadows based on a lighting model).<\/p>\n<h3><span style=\"font-family: courier; font-size: large;\">Modifier.dropShadow()<\/span><\/h3>\n<p>The <span style=\"color: #0d904f; font-family: courier;\">dropShadow()<\/span> modifier draws a shadow behind your content. You can add it to your composable chain and specify the radius, color, and spread. Remember, content that should appear on top of the shadow (like a background) should be drawn <i><a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/modifiers#order-modifier-matters\" target=\"_blank\" rel=\"noopener\">after<\/a><\/i> the <span style=\"color: #0d904f; font-family: courier;\">dropShadow()<\/span> modifier.<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: #aa22ff;\">@Composable<\/span>\n<span style=\"color: #aa22ff;\">@Preview<\/span>(showBackground<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">true<\/span>)\n<span style=\"color: green; font-weight: bold;\">fun<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue;\">SimpleDropShadowUsage<\/span>()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">pinkColor<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color(<span style=\"color: #666666;\">0<\/span>xFFe91e63)\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">purpleColor<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color(<span style=\"color: #666666;\">0<\/span>xFF9c27b0)\n<span style=\"color: #bbbbbb;\">    <\/span>Box(Modifier.<span style=\"color: #687822;\">fillMaxSize<\/span>())<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span>Box(\n<span style=\"color: #bbbbbb;\">            <\/span>Modifier\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">size<\/span>(<span style=\"color: #666666;\">200.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">align<\/span>(Alignment.<span style=\"color: #687822;\">Center<\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">dropShadow<\/span>(\n<span style=\"color: #bbbbbb;\">                    <\/span>RoundedCornerShape(<span style=\"color: #666666;\">20.<\/span>dp),\n<span style=\"color: #bbbbbb;\">                    <\/span>dropShadow<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>DropShadow(\n<span style=\"color: #bbbbbb;\">                        <\/span><span style=\"color: #666666;\">15.<\/span>dp,\n<span style=\"color: #bbbbbb;\">                        <\/span>color<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>pinkColor,\n<span style=\"color: #bbbbbb;\">                        <\/span>spread<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">10.<\/span>dp,\n<span style=\"color: #bbbbbb;\">                        <\/span>alpha<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">0.5f<\/span>\n<span style=\"color: #bbbbbb;\">                    <\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">background<\/span>(\n<span style=\"color: #bbbbbb;\">                    <\/span>purpleColor,\n<span style=\"color: #bbbbbb;\">                    <\/span>shape<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>RoundedCornerShape(<span style=\"color: #666666;\">20.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                <\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>)\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"drop shadow drawn all around shape\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhkx0O88QPkKmPmYP7DQioF7lLapqzNBTczqqHtzEc2VeDnQ8GRsri6-hU-O4OWMGfyQ9rMzz-S03NG30CXtXkJkh6Y-zkmtr1ZQsOYVWLC7AwC1ZWD73I93jvMRGZ0VP-5HlPbOU_S-77Aorc7RIqQbNZlBqKL4kvwa5hX8yVTYZHyCLBzMU85Yy3LKI4\/s1600\/drop-shadow-compose-1-9-release.png\" width=\"50%\"\/><\/div>\n<p><imgcaption><center><em><b>Figure 1.<\/b> Drop shadow drawn all around shape<\/em><\/center><\/imgcaption><\/image><\/p>\n<h3><span style=\"font-family: courier; font-size: large;\">Modifier.innerShadow()<\/span><\/h3>\n<p>The <span style=\"color: #0d904f; font-family: courier;\">Modifier.innerShadow()<\/span> draws shadows on the inset of the provided shape:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: #aa22ff;\">@Composable<\/span>\n<span style=\"color: #aa22ff;\">@Preview<\/span>(showBackground<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">true<\/span>)\n<span style=\"color: green; font-weight: bold;\">fun<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue;\">SimpleInnerShadowUsage<\/span>()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">pinkColor<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color(<span style=\"color: #666666;\">0<\/span>xFFe91e63)\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">purpleColor<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color(<span style=\"color: #666666;\">0<\/span>xFF9c27b0)\n<span style=\"color: #bbbbbb;\">    <\/span>Box(Modifier.<span style=\"color: #687822;\">fillMaxSize<\/span>())<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span>Box(\n<span style=\"color: #bbbbbb;\">            <\/span>Modifier\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">size<\/span>(<span style=\"color: #666666;\">200.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">align<\/span>(Alignment.<span style=\"color: #687822;\">Center<\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">background<\/span>(\n<span style=\"color: #bbbbbb;\">                    <\/span>purpleColor,\n<span style=\"color: #bbbbbb;\">                    <\/span>shape<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>RoundedCornerShape(<span style=\"color: #666666;\">20.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                <\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">innerShadow<\/span>(\n<span style=\"color: #bbbbbb;\">                    <\/span>RoundedCornerShape(<span style=\"color: #666666;\">20.<\/span>dp),\n<span style=\"color: #bbbbbb;\">                    <\/span>innerShadow<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>InnerShadow(\n<span style=\"color: #bbbbbb;\">                        <\/span><span style=\"color: #666666;\">15.<\/span>dp,\n<span style=\"color: #bbbbbb;\">                        <\/span>color<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color.<span style=\"color: #687822;\">Black<\/span>,\n<span style=\"color: #bbbbbb;\">                        <\/span>spread<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">10.<\/span>dp,\n<span style=\"color: #bbbbbb;\">                        <\/span>alpha<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">0.5f<\/span>\n<span style=\"color: #bbbbbb;\">                    <\/span>)\n<span style=\"color: #bbbbbb;\">                <\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>)\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"modifier.innerShadow() applied to a shape\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhP-0J86CPxEGq41sFEpALbcJxPSAtQHaY-j7GT10vx8ig6U6yLtxgzfrO-FXwIcrJPRlWVN9hHwvREL62yWf6tUN8-UH4XU4b-5TFKG_hkTJcZPaxgJRXYa8z-03jePXgm0ebRgL7ugMAlFZhIfs0gaRXhU1E2J6Zvp3hx1s80Bns19KGQWr76dtWmdUA\/s1600\/modifier-innershadow-applied-to-shape-compose-1-9-release.png\" width=\"50%\"\/><\/div>\n<p><imgcaption><center><em><b>Figure 2.<\/b> <span style=\"color: #0d904f; font-family: courier;\">Modifier.innerShadow()<\/span> applied to a shape<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>The order for inner shadows is very important. The inner shadow draws on top of the content, so for the example above, we needed to move the inner shadow modifier after the background modifier. We\u2019d need to do something similar when using it on top of something like an <span style=\"color: #0d904f; font-family: courier;\">Image<\/span>. In this example, we\u2019ve placed a separate <span style=\"color: #0d904f; font-family: courier;\">Box<\/span> to render the shadow in the layer above the image:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: #aa22ff;\">@Composable<\/span>\n<span style=\"color: #aa22ff;\">@Preview<\/span>(showBackground<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">true<\/span>)\n<span style=\"color: green; font-weight: bold;\">fun<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue;\">PhotoInnerShadowExample<\/span>()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span>Box(Modifier.<span style=\"color: #687822;\">fillMaxSize<\/span>())<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">shape<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>RoundedCornerShape(<span style=\"color: #666666;\">20.<\/span>dp)\n<span style=\"color: #bbbbbb;\">        <\/span>Box(\n<span style=\"color: #bbbbbb;\">            <\/span>Modifier\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">size<\/span>(<span style=\"color: #666666;\">200.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">align<\/span>(Alignment.<span style=\"color: #687822;\">Center<\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">            <\/span>Image(\n<span style=\"color: #bbbbbb;\">                <\/span>painter<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>painterResource(id<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>R.<span style=\"color: #687822;\">drawable<\/span>.<span style=\"color: #687822;\">cape_town<\/span>),\n<span style=\"color: #bbbbbb;\">                <\/span>contentDescription<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #ba2121;\">\"Image with Inner Shadow\"<\/span>,\n<span style=\"color: #bbbbbb;\">                <\/span>contentScale<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>ContentScale.<span style=\"color: #687822;\">Crop<\/span>,\n<span style=\"color: #bbbbbb;\">                <\/span>modifier<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Modifier.<span style=\"color: #687822;\">fillMaxSize<\/span>()\n<span style=\"color: #bbbbbb;\">                    <\/span>.<span style=\"color: #687822;\">clip<\/span>(shape)\n<span style=\"color: #bbbbbb;\">            <\/span>)\n<span style=\"color: #bbbbbb;\">            <\/span>Box(\n<span style=\"color: #bbbbbb;\">                <\/span>modifier<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Modifier.<span style=\"color: #687822;\">fillMaxSize<\/span>()\n<span style=\"color: #bbbbbb;\">                    <\/span>.<span style=\"color: #687822;\">innerShadow<\/span>(\n<span style=\"color: #bbbbbb;\">                        <\/span>shape,\n<span style=\"color: #bbbbbb;\">                        <\/span>innerShadow<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>InnerShadow(<span style=\"color: #666666;\">15.<\/span>dp,\n<span style=\"color: #bbbbbb;\">                            <\/span>spread<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">15.<\/span>dp)\n<span style=\"color: #bbbbbb;\">                    <\/span>)\n<span style=\"color: #bbbbbb;\">            <\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>}\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"Inner shadow on top of an image\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEginsTdhyaUmfOAc3xxHg7b2inaQx8WChTxUQGdFLsU4J8aZuWBlqCudumE4092OxYJyoMOKQ7mUMMHae9pHPvi3caLZ-LYHfAGqfuww8Dgl2MK3_mPmHQmuX2iyW35-aVpQZB5FZiv60Np9rGa2r1vqvaTHvhTRGilg6JMzpdfeYvJgHgqQPR5c9NWAWA\/s1600\/inner-shadow-on-top-image-compose-1-9-release.png\" width=\"50%\"\/><\/div>\n<p><imgcaption><center><em><b>Figure 3.<\/b>Inner shadow on top of an image<\/em><\/center><\/imgcaption><\/image><\/p>\n<h2><span style=\"font-size: x-large;\">New Visibility modifiers<\/span><\/h2>\n<p>Compose UI 1.8 introduced <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.onLayoutRectChanged%28kotlin.Long,kotlin.Long,kotlin.Function1%29\" target=\"_blank\" rel=\"noopener\">onLayoutRectChanged<\/a><\/span>, a new performant way to track the location of elements on screen. We&#8217;re building on top of this API to support common use cases by introducing <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.onVisibilityChanged%28kotlin.Long,kotlin.Float,androidx.compose.ui.layout.LayoutBoundsHolder,kotlin.Function1%29\" target=\"_blank\" rel=\"noopener\">onVisibilityChanged<\/a><\/span> and <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/Modifier#%28androidx.compose.ui.Modifier%29.onFirstVisible%28kotlin.Long,kotlin.Float,androidx.compose.ui.layout.LayoutBoundsHolder,kotlin.Function0%29\" target=\"_blank\" rel=\"noopener\">onFirstVisible<\/a><\/span>.  These APIs accept optional parameters for the minimum fraction or amount of time the item has been visible for before invoking your action.<\/p>\n<p>Use <span style=\"color: #0d904f; font-family: courier;\">onVisibilityChanged<\/span> for UI changes or side effects that should happen based on visibility, like automatically playing and pausing videos or starting an animation:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/>LazyColumn<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">  <\/span>items(feedData)<span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span>video<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">-&gt;<\/span>\n<span style=\"color: #bbbbbb;\">    <\/span>VideoRow(\n<span style=\"color: #bbbbbb;\">        <\/span>video,\n<span style=\"color: #bbbbbb;\">        <\/span>Modifier.<span style=\"color: #687822;\">onVisibilityChanged<\/span>(minDurationMs<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">500<\/span>,<span style=\"color: #bbbbbb;\"> <\/span>minFractionVisible<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">1f<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">          <\/span>visible<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">-&gt;<\/span>\n<span style=\"color: #bbbbbb;\">            <\/span><span style=\"color: green; font-weight: bold;\">if<\/span><span style=\"color: #bbbbbb;\"> <\/span>(visible)<span style=\"color: #bbbbbb;\"> <\/span>video.<span style=\"color: #687822;\">play<\/span>()<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">else<\/span><span style=\"color: #bbbbbb;\"> <\/span>video.<span style=\"color: #687822;\">pause<\/span>()\n<span style=\"color: #bbbbbb;\">          <\/span>},\n<span style=\"color: #bbbbbb;\">    <\/span>)\n<span style=\"color: #bbbbbb;\">  <\/span>}\n}\n<\/pre>\n<\/div>\n<p>Use <span style=\"color: #0d904f; font-family: courier;\">onFirstVisible<\/span> for use cases when you wish to react to an element first becoming visible on screen for example to log impressions:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/>LazyColumn<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span>items(<span style=\"color: #666666;\">100<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span>Box(\n<span style=\"color: #bbbbbb;\">            <\/span>Modifier\n<span style=\"color: #bbbbbb;\">                <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Log impressions when item has been visible for 500ms<\/span>\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">onFirstVisible<\/span>(minDurationMs<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">500<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/* log impression *\/<\/span><span style=\"color: #bbbbbb;\"> <\/span>}\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">clip<\/span>(RoundedCornerShape(<span style=\"color: #666666;\">16.<\/span>dp))\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">drawBehind<\/span><span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span>drawRect(backgroundColor)<span style=\"color: #bbbbbb;\"> <\/span>}\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">fillMaxWidth<\/span>()\n<span style=\"color: #bbbbbb;\">                <\/span>.<span style=\"color: #687822;\">height<\/span>(<span style=\"color: #666666;\">100.<\/span>dp)\n<span style=\"color: #bbbbbb;\">        <\/span>)\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">Rich styling in <span style=\"font-family: courier;\">OutputTransformation<\/span><\/span><\/h2>\n<p><span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/text\/package-summary#BasicTextField%28androidx.compose.foundation.text.input.TextFieldState,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.text.input.InputTransformation,androidx.compose.ui.text.TextStyle,androidx.compose.foundation.text.KeyboardOptions,androidx.compose.foundation.text.input.KeyboardActionHandler,androidx.compose.foundation.text.input.TextFieldLineLimits,kotlin.Function2,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.ui.graphics.Brush,androidx.compose.foundation.text.input.OutputTransformation,androidx.compose.foundation.text.input.TextFieldDecorator,androidx.compose.foundation.ScrollState%29\" target=\"_blank\" rel=\"noopener\">BasicTextField<\/a><\/span> now supports applying styles like color and font weight from within an <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/text\/input\/OutputTransformation\" target=\"_blank\" rel=\"noopener\">OutputTransformation<\/a><\/span>.<\/p>\n<p>The new <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/text\/input\/TextFieldBuffer?hl=en#public-functions_1\" target=\"_blank\" rel=\"noopener\">TextFieldBuffer.addStyle()<\/a><\/span> methods let you apply a <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/text\/SpanStyle\" target=\"_blank\" rel=\"noopener\">SpanStyle<\/a><\/span> or <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/ui\/text\/ParagraphStyle\" target=\"_blank\" rel=\"noopener\">ParagraphStyle<\/a><\/span> to change the appearance of text, without changing the underlying <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/text\/input\/TextFieldState\" target=\"_blank\" rel=\"noopener\">TextFieldState<\/a><\/span>. This is useful for visually formatting input, like phone numbers or credit cards. This method can only be called inside an <span style=\"color: #0d904f; font-family: courier;\">OutputTransformation<\/span>.<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Format a phone number and color the punctuation<\/span>\n<span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">phoneTransformation<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>OutputTransformation<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ 1234567890 -&gt; (123) 456-7890<\/span>\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">if<\/span><span style=\"color: #bbbbbb;\"> <\/span>(length<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">==<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">10<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span>insert(<span style=\"color: #666666;\">0<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #ba2121;\">\"(\"<\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>insert(<span style=\"color: #666666;\">4<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #ba2121;\">\") \"<\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>insert(<span style=\"color: #666666;\">9<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #ba2121;\">\"-\"<\/span>)\n\n<span style=\"color: #bbbbbb;\">        <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Color the added punctuation<\/span>\n<span style=\"color: #bbbbbb;\">        <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">gray<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Color(<span style=\"color: #666666;\">0<\/span>xFF666666)\n<span style=\"color: #bbbbbb;\">        <\/span>addStyle(SpanStyle(color<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>gray),<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">0<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">1<\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>addStyle(SpanStyle(color<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>gray),<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">4<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">5<\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>addStyle(SpanStyle(color<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>gray),<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">9<\/span>,<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">10<\/span>)\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n\nBasicTextField(\n<span style=\"color: #bbbbbb;\">    <\/span>state<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>myTextFieldState,\n<span style=\"color: #bbbbbb;\">    <\/span>outputTransformation<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>phoneTransformation\n)\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">LazyLayout<\/span><\/h2>\n<p>The building blocks of <span style=\"color: #0d904f; font-family: courier;\">LazyLayout<\/span> are all now stable! Check out <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/lazy\/layout\/LazyLayoutMeasurePolicy\" target=\"_blank\" rel=\"noopener\">LazyLayoutMeasurePolicy<\/a><\/span>, <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/lazy\/layout\/LazyLayoutItemProvider\" target=\"_blank\" rel=\"noopener\">LazyLayoutItemProvider<\/a><\/span>, and <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/lazy\/layout\/LazyLayoutPrefetchState\" target=\"_blank\" rel=\"noopener\">LazyLayoutPrefetchState<\/a><\/span> to build your own Lazy components.<\/p>\n<h3><span style=\"font-size: large;\">Prefetch Improvements<\/span><\/h3>\n<p>There are now significant scroll performance improvements in <a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/lists#lazy\" target=\"_blank\" rel=\"noopener\">Lazy List<\/a> and <a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/lists#lazy-grids\" target=\"_blank\" rel=\"noopener\">Lazy Grid<\/a> with the introduction of new prefetch behavior. You can now define a <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/lazy\/layout\/LazyLayoutCacheWindow\" target=\"_blank\" rel=\"noopener\">LazyLayoutCacheWindow<\/a><\/span> to prefetch more content. By default, only one item is composed ahead of time in the direction of scrolling, and after something scrolls off screen it is discarded. You can now customize the amount of items ahead to prefetch and behind to retain through a fraction of the viewport or dp size. When you opt into using <span style=\"color: #0d904f; font-family: courier;\">LazyLayoutCacheWindow<\/span>, items begin prefetching in the ahead area straight away.<\/p>\n<p>The configuration entry point for this is on <span style=\"color: #0d904f; font-family: courier;\">LazyListState<\/span>, which takes in the cache window size:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: #aa22ff;\">@OptIn<\/span>(ExperimentalFoundationApi<span style=\"color: #666666;\">::<\/span>class)\n<span style=\"color: #aa22ff;\">@Composable<\/span>\n<span style=\"color: green; font-weight: bold;\">private<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">fun<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue;\">LazyColumnCacheWindowDemo<\/span>()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Prefetch items 150.dp ahead and retain items 100.dp behind the visible viewport<\/span>\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">dpCacheWindow<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>LazyLayoutCacheWindow(ahead<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">150.<\/span>dp,<span style=\"color: #bbbbbb;\"> <\/span>behind<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">100.<\/span>dp)\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Alternatively, prefetch\/retain items as a fraction of the list size<\/span>\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ val fractionCacheWindow = LazyLayoutCacheWindow(aheadFraction = 1f, behindFraction = 0.5f)<\/span>\n<span style=\"color: #bbbbbb;\">    <\/span><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">state<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>rememberLazyListState(cacheWindow<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>dpCacheWindow)\n<span style=\"color: #bbbbbb;\">    <\/span>LazyColumn(state<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>state)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span>items(<span style=\"color: #666666;\">1000<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span>Text(text<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #ba2121;\">\"<\/span><span style=\"color: #a45a77; font-weight: bold;\">$<\/span>it<span style=\"color: #ba2121;\">\"<\/span>,<span style=\"color: #bbbbbb;\"> <\/span>fontSize<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">80.<\/span>sp)<span style=\"color: #bbbbbb;\"> <\/span>}\n<span style=\"color: #bbbbbb;\">    <\/span>}\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"lazylayout in Compose 1.9 release\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjgy5OdlckeFcZuSlyCuCBHV_M2sFryP2Mn0YRz8sTfeFNf7PZxIrPRBBKT6kTdV9uWjizUh2Rz8na7bGZVJ1jb8QWRy9jQNzk1idIM3sxqUcjNm0tlOBGg_Fr1bo7DZ4-aeOdI0ZSFioZwssaGEgnRXl4UzYSMgs03dJUmgv8GQ5z3vvyA_U_khZsb1jc\/s1600\/lazylayout-compose-1-9-release.png\" width=\"70%\"\/><\/div>\n<p><\/image><\/p>\n<blockquote><p><b>Note:<\/b> Prefetch composes more items than are currently visible \u2014 the new cache window API will likely increase prefetching. This means that item&#8217;s <span style=\"color: #0d904f; font-family: courier;\">LaunchedEffects<\/span> and <span style=\"color: #0d904f; font-family: courier;\">DisposableEffects<\/span> may run earlier \u2013 do not use this as a signal for visibility e.g. for impression tracking. Instead, we recommend using the new <span style=\"color: #0d904f; font-family: courier;\">onFirstVisible<\/span> and <span style=\"color: #0d904f; font-family: courier;\">onVisibilityChanged<\/span> APIs. Even if you&#8217;re not manually customizing <span style=\"color: #0d904f; font-family: courier;\">LazyLayoutCacheWindow<\/span> now, avoid using composition effects as a signal of content visibility, as this new prefetch mechanism will be enabled by default in a future release.<\/p><\/blockquote>\n<h2><span style=\"font-size: x-large;\">Scroll<\/span><\/h2>\n<h3><span style=\"font-size: large;\">2D Scroll APIs<\/span><\/h3>\n<p>Following the release of <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/gestures\/package-summary#%28androidx.compose.ui.Modifier%29.draggable2D%28androidx.compose.foundation.gestures.Draggable2DState,kotlin.Boolean,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Boolean,kotlin.Function1,kotlin.Function1,kotlin.Boolean%29\" target=\"_blank\" rel=\"noopener\">Draggable2D<\/a><\/span>, <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/foundation\/gestures\/package-summary#%28androidx.compose.ui.Modifier%29.scrollable2D%28androidx.compose.foundation.gestures.Scrollable2DState,kotlin.Boolean,androidx.compose.foundation.OverscrollEffect,androidx.compose.foundation.gestures.FlingBehavior,androidx.compose.foundation.interaction.MutableInteractionSource%29\" target=\"_blank\" rel=\"noopener\">Scrollable2D<\/a><\/span> is now available, bringing two-dimensional scrolling to Compose. While the existing <span style=\"font-family: courier;\">Scrollable<\/span> modifier handles single-orientation scrolling, <span style=\"color: #0d904f; font-family: courier;\">Scrollable2D<\/span> enables both scrolling and flinging in 2D. This allows you to create more complex layouts that move in all directions, such as spreadsheets or image viewers. Nested scrolling is also supported, accommodating 2D scenarios.<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: green; font-weight: bold;\">val<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #19177c;\">offset<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>remember<span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span>mutableStateOf(Offset.<span style=\"color: #687822;\">Zero<\/span>)<span style=\"color: #bbbbbb;\"> <\/span>}\nBox(\n<span style=\"color: #bbbbbb;\">    <\/span>Modifier.<span style=\"color: #687822;\">size<\/span>(<span style=\"color: #666666;\">150.<\/span>dp)\n<span style=\"color: #bbbbbb;\">        <\/span>.<span style=\"color: #687822;\">scrollable2D<\/span>(\n<span style=\"color: #bbbbbb;\">            <\/span>state<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span>\n<span style=\"color: #bbbbbb;\">                <\/span>rememberScrollable2DState<span style=\"color: #bbbbbb;\"> <\/span>{<span style=\"color: #bbbbbb;\"> <\/span>delta<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">-&gt;<\/span>\n<span style=\"color: #bbbbbb;\">                    <\/span>offset.<span style=\"color: #687822;\">value<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>offset.<span style=\"color: #687822;\">value<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">+<\/span><span style=\"color: #bbbbbb;\"> <\/span>delta<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ update the state<\/span>\n<span style=\"color: #bbbbbb;\">                    <\/span>delta<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ indicate that we consumed all the pixels available<\/span>\n<span style=\"color: #bbbbbb;\">                <\/span>}\n<span style=\"color: #bbbbbb;\">        <\/span>)\n<span style=\"color: #bbbbbb;\">        <\/span>.<span style=\"color: #687822;\">background<\/span>(Color.<span style=\"color: #687822;\">LightGray<\/span>),\n<span style=\"color: #bbbbbb;\">    <\/span>contentAlignment<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>Alignment.<span style=\"color: #687822;\">Center<\/span>,\n)<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">    <\/span>Text(\n<span style=\"color: #bbbbbb;\">        <\/span><span style=\"color: #ba2121;\">\"X=<\/span><span style=\"color: #a45a77; font-weight: bold;\">${<\/span>offset.<span style=\"color: #687822;\">value<\/span>.<span style=\"color: #687822;\">x<\/span>.<span style=\"color: #687822;\">roundToInt<\/span>()<span style=\"color: #a45a77; font-weight: bold;\">}<\/span><span style=\"color: #ba2121;\"> Y=<\/span><span style=\"color: #a45a77; font-weight: bold;\">${<\/span>offset.<span style=\"color: #687822;\">value<\/span>.<span style=\"color: #687822;\">y<\/span>.<span style=\"color: #687822;\">roundToInt<\/span>()<span style=\"color: #a45a77; font-weight: bold;\">}<\/span><span style=\"color: #ba2121;\">\"<\/span>,\n<span style=\"color: #bbbbbb;\">        <\/span>style<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span>TextStyle(fontSize<span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">=<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: #666666;\">32.<\/span>sp),\n<span style=\"color: #bbbbbb;\">    <\/span>)\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"moving image of 2D scroll API demo\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEj293HBOXdNHIJtHSWro5CrgZTyoGFF9VbulPDNvsKYXYa4VmK9OBhnU1pjQk7zKfjRmjRlG03bgvzt31SQ360yAc96vVFOPRCpsu4eNT-ZvOnFkoE024WhFvHk1n9-udTCY-3_I2hcysmJJJNUOGuXRQBe1RPZzbE6g5I0J-YPpYSD37OxhQL0ExT45X4\/s1600\/2D-scroll-API-demo-compose-1-9-release.gif\" width=\"40%\"\/><\/div>\n<p><\/image><\/p>\n<h3><span style=\"font-size: large;\">Scroll Interop Improvements<\/span><\/h3>\n<p>There are bug fixes and new features to improve scroll and nested scroll interop with Views, including the following:<\/p>\n<ul>\n<ul>\n<li>Fixed the dispatching of incorrect velocities during fling animations between Compose and Views.<\/li>\n<\/ul>\n<ul>\n<li>Compose now correctly invokes the View&#8217;s nested scroll callbacks in the appropriate order.<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">Improve crash analysis by adding source info to stack traces<\/span><\/h2>\n<p>We have heard from you that it can be hard to debug Compose crashes when your own code does not appear in the stack trace. To address this we&#8217;re providing a new, opt-in API to provide richer crash location details, including composable names and locations enabling you to:<\/p>\n<ul>\n<ul>\n<li>Efficiently identify and resolve crash sources.<\/li>\n<\/ul>\n<ul>\n<li>More easily isolate crashes for reproducible samples.<\/li>\n<\/ul>\n<ul>\n<li>Investigate crashes that previously only showed internal stack frames.<\/li>\n<\/ul>\n<\/ul>\n<p>Note that we do not recommend using this API in release builds due to the performance impact of collecting this extra information, nor does it work in minified apks.<\/p>\n<p>To enable this feature,  add the line below to the application entry point. Ideally, this configuration should be performed before any compositions are created to ensure that the stack trace information is collected:<\/p>\n<p><!--Kotlin--><\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span\/><span style=\"color: green; font-weight: bold;\">class<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue; font-weight: bold;\">App<\/span><span style=\"color: #bbbbbb;\"> <\/span>:<span style=\"color: #bbbbbb;\"> <\/span>Application()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">   <\/span><span style=\"color: green; font-weight: bold;\">override<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: green; font-weight: bold;\">fun<\/span><span style=\"color: #bbbbbb;\"> <\/span><span style=\"color: blue;\">onCreate<\/span>()<span style=\"color: #bbbbbb;\"> <\/span>{\n<span style=\"color: #bbbbbb;\">        <\/span><span style=\"color: #3d7b7b; font-style: italic;\">\/\/ Enable only for debug flavor to avoid perf regressions in release<\/span>\n<span style=\"color: #bbbbbb;\">        <\/span>Composer.<span style=\"color: #687822;\">setDiagnosticStackTraceEnabled<\/span>(BuildConfig.<span style=\"color: #687822;\">DEBUG<\/span>)\n<span style=\"color: #bbbbbb;\">   <\/span>}\n}\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">New annotations and Lint checks<\/span><\/h2>\n<p>We are introducing a new runtime-annotation library that exposes annotations used by the compiler and tooling (such as lint checks). This allows non-Compose modules to use these annotations without a dependency on the Compose runtime library. The <span style=\"color: #0d904f; font-family: courier;\">@Stable<\/span>, <span style=\"color: #0d904f; font-family: courier;\">@Immutable<\/span>, and <span style=\"color: #0d904f; font-family: courier;\">@StableMarker<\/span> annotations have moved to runtime-annotation, allowing you to annotate classes and functions that do not depend on Compose.<\/p>\n<p>Additionally, we have added two new annotations and corresponding lint checks:<\/p>\n<ul>\n<ul>\n<li><span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/runtime\/annotation\/RememberInComposition\" target=\"_blank\" rel=\"noopener\">@RememberInComposition<\/a><\/span>: An annotation that can mark constructors, functions, and property getters, to indicate that they must not be called directly inside composition without being remembered. Errors will be raised by a corresponding lint check.<\/li>\n<\/ul>\n<ul>\n<li><span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/runtime\/annotation\/FrequentlyChangingValue\" target=\"_blank\" rel=\"noopener\">@FrequentlyChangingValue<\/a><\/span>: An annotation that can mark functions, and property getters, to indicate that they should not be called directly inside composition, as this may cause frequent recompositions (for example,  marking scroll position values and animating values). Warnings are provided by a corresponding lint check.<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">Additional updates<\/span><\/h2>\n<ul>\n<ul>\n<li>To simplify compatibility and improve stability for lint check support, Compose now requires Android Gradle Plugin (AGP) \/ Lint version 8.8.2 or higher. Check out this new <a href=\"https:\/\/developer.android.com\/develop\/ui\/compose\/tooling\/lint\" target=\"_blank\" rel=\"noopener\">documentation page<\/a> to learn more.<\/li>\n<\/ul>\n<ul>\n<li>Two new APIs have been added for context menus:<\/li>\n<\/ul>\n<\/ul>\n<h2><span style=\"font-size: x-large;\">Get started<\/span><\/h2>\n<p>We appreciate all bug reports and feature requests submitted to our <a href=\"http:\/\/goo.gle\/compose-feedback\" target=\"_blank\" rel=\"noopener\">issue tracker<\/a>. Your feedback allows us to build the APIs you need in your apps. Happy composing!<\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"http:\/\/android-developers.googleblog.com\/2025\/08\/whats-new-in-jetpack-compose-august-25-release.html\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Posted by Meghan Mehta \u2013 Developer Relations Engineer and Nick Butcher \u2013 Product Manager Today, the Jetpack Compose August \u201825 release is stable. This<\/p>\n","protected":false},"author":1,"featured_media":346760,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[146],"tags":[],"_links":{"self":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/346759"}],"collection":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/comments?post=346759"}],"version-history":[{"count":0,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/346759\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media\/346760"}],"wp:attachment":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media?parent=346759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/categories?post=346759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/tags?post=346759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}