Jetpack Compose latest release news lands with version 1.11.0, shipped through the Compose BOM 2026.04.01, and it is a bigger release than the point-version number suggests. Google published the announcement on April 22, 2026, and the official Jetpack Compose April '26 release notes lay out everything that shipped, from a default testing behavior change every team will hit immediately to a batch of experimental layout APIs aimed squarely at screen-level design. If you have been waiting to catch up on the Jetpack Compose latest release before touching your build.gradle, this is the practical rundown.

The headline story in this Jetpack Compose latest release is a split between "must deal with now" and "worth experimenting with." The v2 testing APIs becoming the default is not optional — it changes how your existing Compose tests execute. Trackpad input handling and preview wrappers are smaller but immediately useful. Grid, FlexBox, Styles, and MediaQuery are all marked experimental, previewing where two-dimensional, adaptive layout in Compose is headed next. Below is a complete tour of the top features in this release, migration notes on what actually breaks, gotchas, and a verdict on whether to upgrade now.

V2 Testing APIs Are Now Default in the Jetpack Compose Latest Release

This is the change most teams will notice first, and it is the one most likely to break a green test suite overnight. Following the opt-in period introduced back in Compose 1.10, the v2 testing APIs are now the default in this Jetpack Compose latest release, and the v1 APIs are deprecated. The practical effect: the test coroutine dispatcher switches from something that ran launched coroutines eagerly to a StandardTestDispatcher, which queues coroutines instead of running them immediately.

That means a coroutine launched inside a composable under test — say, from a LaunchedEffect — no longer executes until you explicitly advance the virtual clock. Tests that quietly relied on eager execution will now see stale UI state until you call advanceUntilIdle() or step the scheduler yourself.

kotlin
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test

@Composable
fun WelcomeBanner() {
    var message by remember { mutableStateOf("Loading...") }
    LaunchedEffect(Unit) {
        delay(100)
        message = "Welcome back!"
    }
    Column { Text(message) }
}

class WelcomeBannerTest {
    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun bannerUpdatesAfterEffectRuns() = runTest {
        composeTestRule.setContent { WelcomeBanner() }

        // Old assumption: the LaunchedEffect had already run by this point.
        // Under the v2 default StandardTestDispatcher, it has not.
        composeTestRule.mainClock.advanceTimeBy(200)
        composeTestRule.waitForIdle()

        composeTestRule.onNodeWithText("Welcome back!").assertExists()
    }
}

Google's own migration guide for the v2 testing APIs is the right first stop if your CI starts flaking after this Jetpack Compose latest release lands. The upside is real: StandardTestDispatcher mimics production timing far more closely than the old unconfined behavior, which means tests that pass now are less likely to hide genuine race conditions.

Trackpad Input Finally Feels Native in This Compose Release

Trackpad handling gets a substantial overhaul in this Jetpack Compose latest release. Previously, trackpad events were funneled through the same pipeline as touch events, which caused a familiar annoyance: clicking and dragging on a trackpad could trigger scrolling instead of the expected drag gesture. Compose 1.11 now classifies trackpad pointer events as PointerType.Mouse instead of PointerType.Touch, and Modifier.scrollable and Modifier.transformable pick this up automatically — no code changes required for the common case.

On API 34 and above, trackpads also gain two-finger swipe and pinch gesture support, redundant touch slop is removed for trackpad pointers, drag-and-drop starts more intuitively, and text fields get double-click and triple-click word/line selection along with desktop-styled context menus. A new performTrackpadInput() testing API lets you validate all of this without a physical device.

kotlin
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerType
import androidx.compose.ui.input.pointer.pointerInput

@Composable
fun TrackpadAwarePanel() {
    var offset by remember { mutableFloatStateOf(0f) }
    var lastPointerType by remember { mutableFloatStateOf(0f) }

    val scrollState = rememberScrollableState { delta ->
        offset += delta
        delta
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .scrollable(state = scrollState, orientation = androidx.compose.foundation.gestures.Orientation.Vertical)
            .pointerInput(Unit) {
                awaitPointerEventScope {
                    while (true) {
                        val event = awaitPointerEvent()
                        val pointer = event.changes.firstOrNull()
                        if (pointer != null && pointer.type == PointerType.Mouse) {
                            // Trackpad drags now arrive here instead of Touch,
                            // so a click-and-drag no longer fights with scrolling.
                            lastPointerType = 1f
                        }
                    }
                }
            }
    )
}

For any app that gets meaningful ChromeOS or foldable-with-trackpad usage, this alone is worth the upgrade — it removes a class of bug reports that were previously nearly impossible to fix cleanly from application code.

Grid Brings Real Two-Dimensional Layouts to Jetpack Compose

Grid is one of the marquee experimental additions in this Jetpack Compose latest release. Row and Column handle linear arrangements well, but screen-level layouts — dashboards, settings panels, anything with cells that need to span multiple rows or columns — have always required hand-rolled Layout or ConstraintLayout code. Grid gives you a track-based API with gaps, cell spanning, and flexible "Fr" sizing units, purpose-built for that kind of structure rather than for scrollable lists.

kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.gridItem
import androidx.compose.foundation.layout.Grid
import androidx.compose.foundation.layout.ExperimentalGridApi
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color

@OptIn(ExperimentalGridApi::class)
@Composable
fun AnalyticsDashboard() {
    Grid(
        modifier = Modifier.fillMaxSize(),
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        androidx.compose.foundation.layout.Box(
            Modifier.gridItem(rowSpan = 2).background(Color(0xFF3F51B5))
        )
        androidx.compose.foundation.layout.Box(
            Modifier.gridItem(columnSpan = 3).background(Color(0xFF009688))
        )
        androidx.compose.foundation.layout.Box(
            Modifier.gridItem(columnSpan = 2).background(Color(0xFFFF7043))
        )
        androidx.compose.foundation.layout.Box(
            Modifier.background(Color(0xFF9C27B0))
        )
    }
}

The design goal is explicit: Grid targets structural, screen-level architecture, while LazyVerticalGrid remains the right tool for scrollable, repeated-item collections. Treating those as two different problems, rather than stretching one API to cover both, is a welcome bit of API design discipline in this Jetpack Compose latest release.

FlexBox Adds Flexible Wrapping Layouts

Alongside Grid, FlexBox brings a CSS-flexbox-style container to Compose: an experimental API for wrapping, growing, and shrinking children across a main axis, with justifyContent, alignItems, and alignContent controls. It is the natural fit for tag lists, filter chips, and any row of variable-width content that should wrap instead of overflow or scroll.

kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.FlexBox
import androidx.compose.foundation.layout.FlexWrap
import androidx.compose.foundation.layout.ExperimentalFlexBoxApi
import androidx.compose.foundation.layout.flex
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalFlexBoxApi::class)
@Composable
fun FilterChipRow(tags: List<String>) {
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        tags.forEach { tag ->
            Text(
                text = tag,
                modifier = Modifier
                    .background(Color(0xFFE0E0E0))
                    .padding(horizontal = 12.dp, vertical = 6.dp)
                    .flex { grow(0f) }
            )
        }
    }
}

Between Grid and FlexBox, this Jetpack Compose latest release gives you two purpose-built tools for the layout problems that previously forced either a rigid Row/Column tree or a drop down to a custom Layout composable.

Styles Bring Declarative Component Customization

Styles is the most conceptually different of the new experimental APIs in this Jetpack Compose latest release. Instead of composing modifiers and passing colors or shapes through parameters, a style block lets you describe a component's visual state — including interaction states like pressed — declaratively, with the framework handling the animated transition between states.

kotlin
import androidx.compose.foundation.layout.ExperimentalStyleApi
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalStyleApi::class)
@Composable
fun GradientLoginButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
    Button(
        onClick = onClick,
        modifier = modifier,
        style = {
            background(Brush.linearGradient(listOf(Color(0xFF7B61FF), Color(0xFF3F8CFF))))
            width(160.dp)
            height(48.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(Brush.linearGradient(listOf(Color(0xFFFF4081), Color(0xFFE53935))))
            }
        }
    ) {
        Text(text = "Log In")
    }
}

Because styles are state-aware and animate automatically, a lot of the boilerplate around AnimatedContent or manual animateColorAsState calls for simple state-based visual changes disappears. It is still marked experimental, so treat it as a preview of direction rather than something to ship to production today.

MediaQuery Adapts UI to Device State Declaratively

MediaQuery is the other big experimental addition, and it targets a genuinely painful problem: reacting to window size, posture, input type, and other environment signals currently requires wiring together WindowInfoTracker, LocalConfiguration, and assorted device-specific checks. MediaQuery collapses that into a single declarative query.

kotlin
import androidx.compose.foundation.layout.ExperimentalMediaQueryApi
import androidx.compose.foundation.layout.UiMediaScope
import androidx.compose.foundation.layout.mediaQuery
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.OptIn

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun AdaptiveVideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        Text("Tabletop layout: controls below the fold, video on top")
    } else if (mediaQuery { windowWidthClass == UiMediaScope.WidthClass.Expanded }) {
        Text("Expanded layout: video and side panel side by side")
    } else {
        Text("Compact layout: video fills the screen")
    }
}

For high-frequency signals, derivedMediaQuery() avoids unnecessary recomposition, and the API supports scope overrides so previews and tests can simulate device states without a physical foldable on hand. Between Grid, FlexBox, and MediaQuery, this Jetpack Compose latest release is clearly pointed at adaptive, large-screen, and foldable UI as a first-class concern rather than an afterthought.

Preview Wrappers Cut Down on Repetitive Preview Boilerplate

A smaller but genuinely useful addition: the new PreviewWrapperProvider interface and @PreviewWrapper annotation let you inject shared logic — most commonly a theme — around every preview that opts in, instead of wrapping each @Preview composable in your theme manually every time.

kotlin
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewWrapper
import androidx.compose.ui.tooling.preview.PreviewWrapperProvider

class AppThemeWrapper : PreviewWrapperProvider {
    @Composable
    override fun Wrap(content: @Composable () -> Unit) {
        MaterialTheme {
            content()
        }
    }
}

@PreviewWrapper(AppThemeWrapper::class)
@Preview
@Composable
private fun SubmitButtonPreview() {
    Button(onClick = {}) {
        Text(text = "Submit")
    }
}

It is a small thing, but on a team with dozens of preview functions, removing one repeated wrapper call per preview adds up quickly, and it keeps theming consistent across the whole preview gallery in Android Studio.

Migration Notes: Breaking Changes in the Jetpack Compose Latest Release

Most existing Compose code compiles and runs unchanged, but a few things need attention before you roll this out broadly:

  • The v2 testing APIs are now the default, and v1 is deprecated. As covered above, any test relying on a LaunchedEffect or other coroutine running eagerly needs an explicit advanceUntilIdle() or equivalent clock advance. Follow the official v2 migration guide module by module rather than all at once.
  • Modifier.onFirstVisible() is deprecated in this Jetpack Compose latest release. Its name misled people into thinking it fired once per composable lifetime, when in practice it could fire multiple times during lazy layout scrolling. Replace it with Modifier.onVisibilityChanged(), which gives more precise, intentional visibility tracking.
  • ComposeFoundationFlags.isTextFieldDpadNavigationEnabled is removed entirely. D-pad navigation for text fields is now always on: D-pad input first moves the text cursor within the field, and focus only jumps to the next element once the cursor reaches the start or end of the text. Apps built for TV or game-console input that depended on the old flag behavior need to re-test focus traversal.
  • Compose 1.12, the next release after this one, will require compileSdk 37 and Android Gradle Plugin 9. That is not a breaking change in 1.11 itself, but it is worth planning your compileSdk and AGP upgrades now so you are not blocked when 1.12 ships.

Gotchas to Watch For After Upgrading

A handful of rough edges show up once teams start using this release in earnest:

  • Every new layout and customization API in this Jetpack Compose latest release — Grid, FlexBox, Styles, MediaQuery — ships behind an @OptIn(Experimental...Api::class) annotation. That is not boilerplate to silence; these APIs can still change shape before graduating to stable, so pin yourself to a specific Compose version if you adopt them in a shipping app.
  • The new SlotTable implementation is included but disabled by default in this release, gated behind ComposeRuntimeFlags.isLinkBufferComposerEnabled. Do not expect any of the promised recomposition-performance gains until you explicitly opt in, and expect it to still be rough around the edges given its experimental status.
  • Trackpad two-finger swipe and pinch gestures only work on API 34 and above. On older API levels, trackpad input still gets the PointerType.Mouse treatment, but the newer multi-finger gestures silently fall back to not being available.
  • Under the v2 testing default, a test that used to pass by accident — because a coroutine happened to finish before an assertion ran — can now fail deterministically. Treat these failures as the test suite catching a real timing assumption, not as noise to work around with a longer delay.
  • Grid and FlexBox are explicitly aimed at screen-level layout, not scrollable collections. Reaching for Grid where LazyVerticalGrid is the right tool (or vice versa) will cost you performance and correctness, not just style points.

Verdict: Should You Upgrade to This Jetpack Compose Latest Release?

Yes, upgrade the BOM soon — but budget real time for the testing migration before you do. The v2 testing APIs becoming default is the one part of this Jetpack Compose latest release that is not optional and not purely additive; it can turn a green CI pipeline red the first time you bump the BOM, so run your full test suite against 1.11 in a branch first and work through the StandardTestDispatcher timing fixes methodically.

Everything else here is close to a free upgrade. Trackpad handling and Preview Wrappers are pure quality-of-life wins with no downside. The deprecation of Modifier.onFirstVisible() and removal of the D-pad navigation flag are easy to grep for and fix in minutes. As for Grid, FlexBox, Styles, and MediaQuery — these are the interesting parts of this Jetpack Compose latest release to watch, but treat them as a preview of Compose's adaptive-layout future rather than something to build production screens on top of today. Prototype with them, file feedback through the linked issue trackers, and plan to revisit once they stabilize.

Putting It Together: Grid and Styles in One Example

This closing example combines two of the release's experimental headline features — the Grid layout for screen-level structure and the Styles API for declarative, state-aware customization — into one self-contained composable:

kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.ExperimentalGridApi
import androidx.compose.foundation.layout.ExperimentalStyleApi
import androidx.compose.foundation.layout.Grid
import androidx.compose.foundation.layout.gridItem
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalGridApi::class, ExperimentalStyleApi::class)
@Composable
fun ReleaseHighlightsScreen() {
    MaterialTheme {
        Grid(
            config = {
                repeat(2) { column(0.5f) }
                repeat(2) { row(0.5f) }
                gap(12.dp)
            }
        ) {
            StyledActionButton(
                label = "Run Tests",
                modifier = Modifier.gridItem(columnSpan = 2)
            )
            StyledActionButton(label = "View Grid Docs")
            StyledActionButton(label = "View FlexBox Docs")
        }
    }
}

@OptIn(ExperimentalStyleApi::class)
@Composable
private fun StyledActionButton(label: String, modifier: Modifier = Modifier) {
    Button(
        onClick = {},
        modifier = modifier,
        style = {
            background(Brush.linearGradient(listOf(Color(0xFF3F51B5), Color(0xFF009688))))
            textAlign(TextAlign.Center)
            externalPadding(12.dp)

            pressed {
                background(Brush.linearGradient(listOf(Color(0xFF303F9F), Color(0xFF00695C))))
            }
        }
    ) {
        Text(text = label)
    }
}

That is the shape of the Jetpack Compose latest release in one screen: a stable, structural layout tool paired with a declarative, animated way to style what sits inside it — a small taste of where Compose's adaptive UI story is headed next.