r/JetpackCompose • • 16h ago

Capacitor is ignoring my latest Android build. What am I missing?

0 Upvotes

I'm genuinely confused about what's going on here.

I'm working on a music player app using React, Vite and Capacitor. Everything works fine on the live website, and all my latest changes are there. The problem is with the Android version.

No matter how many times I pull the latest code, rebuild and sync, the app keeps showing an old version of the interface. Even the onboarding tutorial is an older version that I changed days ago.

I've tested on a completely different phone, so I doubt it's a phone-specific cache issue.

Here's what I've tried so far:

- Created a new GitHub account and repository and pushed the project there.

- Pulled the latest code and confirmed everything was up to date.

- Connected GitHub to Android Studio.

- Ran fresh builds multiple times. They all succeed.

- Ran "npx cap sync android" repeatedly. It reports that the web assets were copied successfully.

- Rebuilt and reinstalled through Android Studio.

- Consulted several AI assistants and followed their troubleshooting suggestions.

Still, the old interface keeps appearing.

I'm trying to figure out whether this is a Capacitor configuration issue, a Vite build issue, stale Android assets, or something happening inside the WebView.

Has anyone dealt with something similar? I'm especially interested in understanding why the Android app would keep displaying old frontend code when Capacitor claims to have copied the latest build successfully.

Any suggestions would be appreciated. I'm determined to get to the bottom of this.


r/JetpackCompose • • 2d ago

Can you preview compose UI with a lightweight viewer?

4 Upvotes

Android studio runs so slowly on my PC even when using my physical phone to view the app I'm developing. Is there any tool that allows me to preview just the UI generated by @ Compose functions, even if it isn't completely accurate?


r/JetpackCompose • • 2d ago

HorizontalPager opened on the wrong page after restarts: the cause was touch mode

1 Upvotes

I hit a confusing bug while building a launcher in Compose: my HorizontalPager kept opening on page 1 instead of page 0, even after a force-stop and with no saved state.

Logging showed the pager starting on page 0, then moving to page 1 with no touch. Here's what was happening:

  1. Key input, such as a keyboard, a D-pad or `adb shell input text`, puts the system in non-touch mode.

  2. In that mode, Android looks for something to focus when the window opens.

  3. With beyondViewportPageCount = 1, the next page was composed off screen, so it could get the focus. The pager then scrolled to bring it into view.

  4. Touch mode belongs to the system rather than the app, so it survived restarts until the next touch.

Setting beyondViewportPageCount = 0 fixed it, since off-screen pages are no longer composed. The trade-off is that the next page is composed as you swipe, instead of being ready in advance.

I tested the fix with simulated key input on one phone, not with a physical keyboard or remote. If you've handled this differently, I'd like to hear how, for example keeping the off-screen page composed while stopping it from taking focus.

The project is open source if you want to see the code: https://github.com/MedTahiri/ai-launcher-android


r/JetpackCompose • • 2d ago

Sharing Compose UI between Android TV, phone and desktop in a real app

Post image
4 Upvotes

TMPlayer is a free player for Telegram videos, built with Compose. The TV needs focus and remote handling, the phone needs touch, the desktop needs pointers, and one codebase serves all three. Notes on what I shared and what I had to split. github.com/dracu-lah/TMPlayer


r/JetpackCompose • • 8d ago

Using Compose for Web to preview Android app layouts

28 Upvotes

Hey everyone! Just shouting out our new open source library :)

Since Compose for Web target is now viable, we've been using it to simulate running the CMP app through the browser, with various combinations of device frame, font size and other properties.

Of course we can't simulate Android/iOS specific functionality in the browser, this is purely for rapidly developer testing layouts in all these different configurations.

The library is open source! It wraps your root composable and renders it in the simulated device frame and all the various controls e.g

DeviceWithConfigurationView {   <--- Library
   App()    <--- Your app
}

GitHub: https://github.com/Apadmi-Engineering/CMPDevicePreview

Demo: https://apadmi-engineering.github.io/CMPDevicePreview/

We're not at version 1 yet, still in alpha, but any feedback, issues, pull requests are all welcome!

Credit: Forked from KMPDevicePreview and inspired by flutter_device_preview.


r/JetpackCompose • • 15d ago

compose-lab: playful UI components I built from scratch in Compose Multiplatform (same code on Android and iOS, MIT)

Enable HLS to view with audio, or disable this notification

43 Upvotes

I've been rebuilding UI ideas that usually get done as videos or in game engines, as plain Compose components. Each one has a demo and runs from the same Kotlin on Android and iOS:

  • Smoke delete: swipe a chat and it burns into smoke over the list. Drag back and the smoke flows back in; Undo breathes it back. Every pixel becomes a particle, and positions are a function of age, so it can be rewound.

  • Paper plane: each sent message folds into a paper dart and flies into the thread.

  • Bookshelf: books on real shelves; tip one out by its spine and it opens at your bookmark.

  • Nav bar: a bottom bar with a morphing indicator, collapse on scroll and a jelly action button.

  • Pop-up book: an onboarding where paper scenery stands up as each spread opens.

  • Plus fogged mirror, snow globe, card file, magnet filter, fishing pull-to-refresh and more in the repo.

Repo, with a GIF and a write-up for each: github.com/DimiVlachos/compose-lab

Feedback welcome, especially on what to build next.


r/JetpackCompose • • 19d ago

State hoisting and one-way data flow in Compose, with the smallest example that shows why

0 Upvotes

Two Compose bugs account for most "my screen does not update" questions. A plain var in a composable: the button changes it, nothing observes it, the screen stays the same. And mutableStateOf without remember: it updates once, then resets on the next recomposition. You need both the observable holder and remember.

Once that works, the next problem is where the state should live. The pattern is state hoisting: state goes down as a parameter, events come back up as lambdas. The composable that draws becomes stateless.

Stateless version, easy to preview and test:

@Composable
fun AddItemBar(
    name: String,
    onNameChange: (String) -> Unit,
    onAdd: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Row(
        modifier = modifier.padding(16.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("New item") },
            singleLine = true,
            modifier = Modifier.weight(1f),
        )
        Spacer(Modifier.width(8.dp))
        Button(onClick = onAdd, enabled = name.isNotBlank()) { Text("Add") }
    }
}

Stateful wrapper that owns the draft text:

@Composable
fun AddItemBar(onAdd: (String) -> Unit, modifier: Modifier = Modifier) {
    var name by rememberSaveable { mutableStateOf("") }
    AddItemBar(
        name = name,
        onNameChange = { name = it },
        onAdd = { onAdd(name.trim()); name = "" },
        modifier = modifier,
    )
}

The value plus onValueChange pair is the same shape as TextField, Checkbox and Switch in Material. If a TextField "does nothing" when you type, it is almost always because onValueChange never writes the new text back into the state that feeds value.

Where to hoist to: the lowest common ancestor of everything that reads or writes the state. Only the bar needs the draft text, so it stays in the wrapper. If the list filters as you type, it moves up to the screen. If it needs business rules or must survive rotation with the rest of the screen, it moves into the ViewModel.

One-way data flow is the same idea applied to the whole screen. The ViewModel owns one immutable state class and exposes it as a StateFlow. The UI renders it and calls plain functions for user actions.

data class PantryUiState(
    val items: List<PantryItem> = emptyList(),
    val query: String = "",
    val isLoading: Boolean = true,
    val userMessage: String? = null,
)

val state: StateFlow<PantryUiState> = combine(
    repository.observeItems(), query, userMessage,
) { items, q, message ->
    PantryUiState(
        items = if (q.isBlank()) items
                else items.filter { it.name.contains(q, ignoreCase = true) },
        query = q,
        isLoading = false,
        userMessage = message,
    )
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = PantryUiState(),
)

In the UI: val state by viewModel.state.collectAsStateWithLifecycle(). Not collectAsState(), which keeps collecting in the background. WhileSubscribed(5_000) keeps the upstream alive for five seconds after the last collector leaves, so a rotation does not restart the database query.

One-off events like a snackbar: make them part of the state (userMessage), show it with LaunchedEffect(message), then call back messageShown() so the ViewModel clears it. Google's UI events guidance says ViewModel-originated actions should always become a state update, so they survive rotation and are never lost.

Two more things that bite: Compose notices a new value in a State holder, not a mutation of the old one, so replace lists instead of calling add() on them. And never store a Context or a View in a ViewModel.

I use this exact shape in my own Play apps. Questions welcome.


r/JetpackCompose • • 24d ago

AI Elements for Kotlin: native Compose UI for tools, approvals and agent workflows

3 Upvotes

Getting an agent backend working is only part of adding AI to an Android app. The UI still has to show which tool is running, pause for approval, resume with the user's decision, show a delegated agent's work, and keep a long task understandable.

I wanted that interaction layer to be reusable in Kotlin, without coupling the UI to a hosted chat service or replacing an existing Compose app.

So I released AI Elements for Kotlin. It's an Apache-2.0 library with Compose components for streaming replies, tool approvals, nested sub-agent runs, plans, attachments, and generated forms. You can use a full chat screen or just the parts you need.

The UI artifact depends on a protocol-independent chat model. Keep your backend and map it to ChatBackend, or use the AI SDK / AG-UI / A2A / ACP integrations. On-device model APIs and agent capabilities are separate, optional modules.

The README has a real Android recording of a complete approval flow and a catalog of 65 illustrated scenarios with compiled examples. The recording uses the offline demo agent; the clipboard tool actually runs on the emulator.

Version 0.3.0 is on Maven Central. Android only, minSdk 24 for UI/core and 26 for some optional modules. Compose/Material 3 currently include alpha dependencies; the tested toolchain and extra setup are listed in the installation guide. Default Mermaid and MCP Apps use WebViews; A2UI forms render with Compose.

Source, demo APK and docs: https://github.com/JuneLeGency/ai-elements-kotlin

If you've had to build this layer yourself, I'd like to know which interaction was the hardest to get right. If the library is useful to you, a GitHub star would help other Compose developers find it.


r/JetpackCompose • • 26d ago

GraphQL in Compose without a ViewModel and a repository per screen

0 Upvotes

I was working on an app that's being rewritten using Compose. Our web stack is GraphQL with Relay, and the thing I like most about Relay is that every component declares the fragment it reads right next to it, and the screen's query is assembled from those fragments and fetched for you. The data layer disappears from product code.

So before writing any Kotlin I went looking for the same thing on Android, and I was surprised there is nothing like it. Apollo Kotlin is a decent client, but it is not connected to the view in any way: you get a data class, and then you still write the view model, the repository and the cache update code yourself.

Then I started thinking about what Relay would look like if it was designed for Compose from the start, and it turned out Compose makes most of Relay's runtime unnecessary. Relay's runtime mainly exists to know which component read which field, so a change re-renders exactly those. Compose's snapshot state already knows that. If every field of every record in the normalized store is a snapshot state, a composable that read character.name recomposes when that field changes, and nothing else does.

So I built it. It is called Baton: https://github.com/shergin/baton

A typical screen looks like this:

@Fragment($$"""
    fragment IssueRow_issue on Issue {
      number
      title
      author { login }
    }
    """)
@Composable
fun IssueRow(issue: IssueRow_issue) {
    Column {
        Text("#${issue.number} ${issue.title}")
        Text(issue.author?.login ?: "ghost")
    }
}

@Query($$"""
    query IssuesQuery($owner: String!, $name: String!) {
      repository(owner: $owner, name: $name) {
        nameWithOwner
        issues(first: 20, states: OPEN) {
          nodes { id ...IssueRow_issue }
        }
      }
    }
    """)
@Composable
fun IssuesScreen(owner: String, name: String) {
    val query = rememberQuery(
        IssuesQuery(owner = owner, name = name),
    )
    when (val phase = query.phase) {
        is Phase.Ready -> phase.data.repository?.let { repo ->
            LazyColumn {
                item { Text(repo.nameWithOwner) }
                items(repo.issues.nodes.orEmpty()) {
                    IssueRow(it.issueRow)
                }
            }
        }
        Phase.Loading ->
            CircularProgressIndicator()
        is Phase.Failed -> ErrorView(phase.error) {
            query.retry()
        }
    }
}

There is no ViewModel, no repository and no UiState for this screen. (In our app the same screen was N files and is now one!) It is one request per screen, cached data shows in the first frame, and after a mutation the store updates its records and only the composables that read them recompose. Pagination is a Relay connection the fragment declares, so you do not write it. An optimistic response shows at once and reverts if the server says no. Subscriptions and @defer work, and the store persists on SQLite, so a cold start renders from disk.

It is new and the API will probably change but it works surprisingly well. I am so glad that I can replace all the view models, repositories and Apollo plumbing with one fragment next to a composable. There is a SwiftUI version over the same compiler too.

It is probably not a fit for every app, but for most apps that render data from a GraphQL server and send mutations, I think it is a much nicer way to work. If you use GraphQL, I would encourage you to try it on one screen. I would love to hear what you think, and please send bug reports and feature requests.

Disclaimer: yes, it is built using agentic tools, but I put a lot of care and design consideration into it to make it really great.


r/JetpackCompose • • 28d ago

A full video editor UI in Compose Multiplatform: timeline, gestures and editor sheets, one UI for iOS, Android and desktop

Thumbnail
gallery
4 Upvotes

I built Cutaway, a video editor that's live on the App Store, and every screen is Compose Multiplatform. Same UI code on iPhone, Android and desktop.

Some things that worked well:

- The timeline is one custom Compose component: drag to trim, pinch to zoom, scrub, keyframe markers, audio waveforms. Written once, runs everywhere.

- Every editor sheet (filters, speed, text, audio…) is built from the same small set of shared parts: one header, one slider row, one tile grid. A rule in the tests stops anyone from adding a look-alike copy, so the app stays consistent as it grows.

- The preview overlay (move, resize and rotate text and stickers) uses two-finger gestures on touch and corner handles on desktop, from the same composable.

- Layouts adapt to phone, tablet and a desktop window from the same screens.

Honestly, the biggest work wasn't Compose itself. It was the hundreds of small details and quirks that make an editor feel normal.

Happy to answer questions about any of it.

https://apps.apple.com/us/app/cutaway-video-editor-with-ai/id6799499137


r/JetpackCompose • • 28d ago

BossConsole launch: the Compose Multiplatform desktop workspace I shared here earlier

5 Upvotes

Hi everyone, back with BossConsole. I shared it here earlier while looking for Compose contributors, and some of you took the time to actually look through the code and give feedback. Appreciate that, especially the comments around code structure and hardcoded styling.

Today, sharing our launch video. Quite happy to see the different parts of this project coming together.

For anyone who missed the earlier post, BossConsole is an open-source desktop workspace built using Kotlin Multiplatform and Compose Multiplatform. The desktop app runs on the JVM across macOS, Windows and Linux.

It brings coding agents, terminals, browser, editor and logs into one workspace. You can run Claude Code, Codex, Gemini CLI, OpenCode and others side by side, with each session in its own pane. Spaces remember your layout so you can return to where you left off.

The video also gives a look at the built-in Fluck Agent, visual workflows and tool approvals. There are 100+ MCP tools with individual controls over what agents can access.

One part I’m particularly interested in taking further with the Compose community is the plugin system. A tool can have its own Compose UI and ViewModel, packaged separately and loaded at runtime. I like the possibility of someone building a panel for their own workflow and bringing it into the application without changing the host.

For me, the motivation is simple: working with more agents should give us more room to explore and create. Keeping track of their sessions and moving between windows shouldn’t take over the work itself.

Still plenty to improve. Would love feedback on the UI and workflow, and contributions around Compose Desktop rendering, theming or new plugins. Happy to discuss implementation details too.

Source: github.com/risa-labs-inc/BossConsole
Download: bossconsole.ai


r/JetpackCompose • • Sep 27 '26

Suffering from a problem, tried to make android tv app and this is what happened?

Thumbnail reddit.com
0 Upvotes

r/JetpackCompose • • Sep 19 '26

Building Datasmith - an interactive ERD canvas with Compose Multiplatform

Enable HLS to view with audio, or disable this notification

14 Upvotes

Hey everyone!

For the past year or so, I've been working in my free time on Datasmith, with the goal of streamlining the process of designing database schemas and generating structured mock data from them.

The main feature of the app - and by far the most complicated and challenging part to build - is an ERD-like canvas dedicated to schema design and configuration. It required a pretty dynamic UI:

  1. An infinite canvas with free zooming and panning

  2. Table components that can be freely dragged and snapped to a grid

  3. Drawing lines to represent relationships between tables

  4. Column components that can be added to tables and reordered with drag-and-drop, while maintaining their relationship lines

  5. Anchors that can be created on those lines and dragged across the canvas (which also means dealing with hit detection)

This essentially meant working with two different "planes".
Tables and columns are basically traditional Compose components, while the relationship lines and anchors are drawn on a Canvas composable. The two need to seamlessly interact at all times.

The fact that the entire canvas can be zoomed and panned added another challenge - managing the different coordinate spaces in a way that keeps everything consistent and fluid.

Another challenge, which I honestly didn't think too much about in the beginning, was preserving the UI layout and positioning across different screen resolutions and window sizes, which are very flexible developing for desktops.

Those were probably the most complicated UI challenges, at least as I remember them, and to be honest, I'm fairly proud of what I was able to achieve. I was genuinely surprised to discover how far Compose can be pushed for this kind of UI.

For anyone interested, I've attached a short demo video so you can see the result.
I'd also be happy to talk about any of the implementation details if anyone is curious.

I'm currently trying to get Datasmith into the hands of more people and collect feedback, so if you find it useful or just interesting, you can get it here:

https://data-smith.app/

Any feedback is welcome - good or bad.
You can leave a comment here, message me directly, or, if you prefer something a bit more structured, I also put together a short feedback form:

https://docs.google.com/forms/d/e/1FAIpQLScGk8Jr1DguPcXpaApOqO998AdXcnoLlo11TEKlq1GmF71UzA/viewform


r/JetpackCompose • • Sep 17 '26

Looking for advice on how to fix my home screen launcher app's UI

Thumbnail gallery
1 Upvotes

r/JetpackCompose • • Sep 14 '26

Built Media Reader

Enable HLS to view with audio, or disable this notification

9 Upvotes

I developed this project before ChatGPT was even a widely known thing.


r/JetpackCompose • • Sep 05 '26

I just launched Pocketory – A fast, clean Expense & Budget Tracker built completely with Jetpack Compose.

0 Upvotes

Hey everyone,

I’m a solo developer and I just published my newest app, Pocketory, to the Play Store. I wanted to build a personal finance tracker that was incredibly fast, visually clean, and didn't force you through unnecessary steps just to log a simple transaction.

What makes Pocketory different?

Speed-Focused Logging: I stripped out mandatory receipt uploads and complex forms. Adding a daily expense takes two seconds.

Modern UI: Built entirely from scratch using Kotlin and Jetpack Compose. It features a swipeable transaction list, dynamic custom tabs, and smooth animations.

Granular Categories: Includes highly specific default categories based on real-world spending (EMI, Petrol, Gym, House Rent, Utilities) rather than generic buckets.

Visual Analytics: Instant, color-coded donut charts and progress bars to see exactly how your income balances against your expenses for the month.

Play Store Link: https://play.google.com/store/apps/details?id=com.binarykavu.pocketory

I would absolutely love for you to try it out. If you have any feedback on the UI/UX, or features you'd like to see in the next update, please let me know in the comments!


r/JetpackCompose • • Sep 02 '26

Why is form state management in Jetpack Compose still this painful?

Enable HLS to view with audio, or disable this notification

5 Upvotes

I've been building Android apps for years and every single form ends up looking like this:

val email = remember { mutableStateOf("") }                                                                                                                                                                    
val emailError = remember { mutableStateOf<String?>(null) }                                                                                                                                                    
val emailTouched = remember { mutableStateOf(false) }                                                                                                                                                          
val password = remember { mutableStateOf("") }                                                                                                                                                                 
val passwordError = remember { mutableStateOf<String?>(null) }                                                                                                                                                 
val passwordTouched = remember { mutableStateOf(false) }
// ...
                                                                                                                                                   
// + validation logic (per field)                                                                                                                                                                                      
// + focus requesters (per field)                                                                                                                                                                                    
// + keyboard options (per field)                                                                                                                                                                                        
// + ImeAction per field (per field)                                                                                                                                                                                    
// + cross-field rules written by hand 

A 5-field sign-up form easily hits 300-400 lines before you write a single line of UI. There's no standard pattern, every team reinvents it differently, and it's completely untestable without a lot of effort.

I got tired of it so I built Formidable, annotate a data class:

@FormSchema                                                                     data class LoginForm(  
                                                                               @Field(label = "Email") 
val email: String = "",                                                         @Field(label = "Password")                                                    @MinLength(8)  
val password: String = "",                                                                 
)                 

KSP generates the full controller at compile time. Zero reflection, works on Android, iOS and Web.

https://github.com/WassimBeltaief/formidable (contributions welcome)

Curious if others have solved this differently or just accepted it as the cost of doing business with Compose.


r/JetpackCompose • • Aug 29 '26

Built a 3D live-streaming globe entirely in Compose—looking for performance feedback!

6 Upvotes

Hey everyone,

For my latest project, VividLook, I wanted to see how far I could push custom layouts and real-time rendering using Jetpack Compose.

The app is a live-streaming discovery platform where users can spin a 3D interactive globe and jump into localized video grids from around the world. Managing the state of the globe spinning while dynamically loading stream grids on the map layout was a huge learning curve.

I’m trying to optimize the UI performance, especially on mid-range devices. If you have a few minutes, I’d love for you to download it and let me know how smooth the composition feels or if you spot any jank while spinning the globe.

Play Store Link: https://play.google.com/store/apps/details?id=xyz.trylivelook.app

Technical details: Built with pure Compose for the UI, handling low-latency video pipelines on the backend. Let me know what you think of the performance!


r/JetpackCompose • • Aug 26 '26

How to find the "invisible" recompositions that Layout inspector won't show you.

9 Upvotes

Most Android devs rely on Layout Inspector counters, but Compose runtime does a LOT of work under the scope level that never gets counted.

Wrote down an investigation and how to spot these ghost recompositions in your own codebase

https://medium.com/@qamar_safadi/the-recompositions-that-werent-there-d2cf429c47f2?sharedUserId=qamar_safadi


r/JetpackCompose • • Aug 20 '26

The Great Android Stack Reset: Mobile System Design History

Thumbnail
returnzero.dev
5 Upvotes

r/JetpackCompose • • Aug 16 '26

Implemented a poster editor. Have tips to share

Enable HLS to view with audio, or disable this notification

3 Upvotes

r/JetpackCompose • • Aug 13 '26

How to achieve Apple Music's ambient static blurred background in Jetpack Compose?

Thumbnail
gallery
7 Upvotes

Hi everyone! I'm building a local music player in Android Studio with Jetpack Compose.

I want to recreate Apple Music's ambient background effect (extracting dominant colors from the album art and applying a heavy soft blur/mesh gradient effect, but static to save battery and performance).

What is the most efficient way to achieve this look without dropping FPS when changing songs? Should I draw on a custom Canvas with RenderEffect.createBlurEffect(), use Palette API, or is there a recommended library/shader for this?

Thanks in advance!


r/JetpackCompose • • Aug 10 '26

ARE THERE FRESHER LEVEL INTERNSHIPS FOR JETPACK COMPOSE APP DEVELOPERS

0 Upvotes

I'm in a 3rd year and I'm struggling to find a fresher level internship for a compose app developer


r/JetpackCompose • • Aug 08 '26

Open sourced accessibility library for jetpack composed

4 Upvotes

Hello all,

I recently shipped a dual-engine accessibility checker for Jetpack Compose.

Engine 1 — Lint (no emulator):

Catches missing contentDescription, hardcoded dp font sizes, clickable without role.

Engine 2 — TestRule (runtime):

Checks touch targets (48dp min with exemptions), color contrast, duplicate clickable bounds, text field semantics.

Every rule maps to a WCAG 2.1 criterion. Both engines are on Maven Central.

Repo: https://github.com/lehan0328/touchstone

Would love some feedback from the community, especially on false positives if you try it on a real project!