Jetpack Compose for AnkiDroid incrementally, starting with a new shared :ui-compose module that houses the theme bridge and reusable UI components. Existing Views/Fragments stay; new screens and migrated leaf screens render in Compose hosted inside the current Fragment shells via ComposeView.
FYI: At I/O 2026 Google formally moved Android UI to "Compose First":
- Android Views, Fragments, RecyclerView, ViewPager, and
android.widget are in maintenance mode critical bug fixes only, no new features (source).
- All new Android Studio UI tooling targets Compose (Layout Editor / Navigation Editor are frozen).
- Compose BOM 2026.04.01 (Compose 1.11) ships Grid, FlexBox, Style API, faster SlotTable runtime (release notes).
- The official guidance is interop-first incremental adoption via
AndroidView / ComposeView (interop docs).
What its worth, AnkiDroid is well-positioned: AGP 9, Kotlin 2.3, minSdk 24, no Hilt/Dagger lock-in, view binding already enabled, small custom-View footprint.
Proposed approach
Phase 0 Foundations
Phase 1: Pilot leaf screens (separate PRs, one per screen)
Low-risk, no shared state, prove the patterns:
AboutFragment (static content)
LoadingDialogFragment, AsyncDialogFragment (dialogs)
PageFragment (WebView + toolbar- proves AndroidView interop) ,etc
Phase 2: Mid-complexity
- Settings sub-screens (will need a strategy for custom
Preference subclasses)
- Info / help screens
Phase 3: Lists
- Card Browser, Deck Picker-
LazyColumn / LazyVerticalGrid
Phase 4: Stateful surfaces
- Reviewer, Note Editor, last, when patterns are well-established
New module: :ui-compose
AnkiDroid already has a :common / :common:android pattern, but a Compose-specific module deserves its own root-level name because its purpose is UI building blocks, not "common utilities." I'd propose:
ui-compose Module Implementation Tasks
:common semantically means "non-UI shared code." Putting UI components there is misleading. :ui-compose is unambiguous and matches Now in Android's core/designsystem convention.
Jetpack Compose for AnkiDroid incrementally, starting with a new shared
:ui-composemodule that houses the theme bridge and reusable UI components. Existing Views/Fragments stay; new screens and migrated leaf screens render in Compose hosted inside the current Fragment shells viaComposeView.Proposed approach
Phase 0 Foundations
:AnkiDroidbuild (compose BOM, kotlin-compose plugin,buildFeatures.compose = true):ui-composemodule (theme + shared components)docs/development/compose.mdPhase 1: Pilot leaf screens (separate PRs, one per screen)
Low-risk, no shared state, prove the patterns:
AboutFragment(static content)LoadingDialogFragment,AsyncDialogFragment(dialogs)PageFragment(WebView + toolbar- provesAndroidViewinterop) ,etcPhase 2: Mid-complexity
Preferencesubclasses)Phase 3: Lists
LazyColumn/LazyVerticalGridPhase 4: Stateful surfaces
New module:
:ui-composeAnkiDroid already has a :common / :common:android pattern, but a Compose-specific module deserves its own root-level name because its purpose is UI building blocks, not "common utilities." I'd propose:
ui-composeModule Implementation TasksBuild Setup
build.gradle: Applykotlin-compose, setcompose=truesrc/main/AndroidManifest.xml: Add baseline manifestTheme (
theme/)AnkiTheme.kt: MaterialTheme wrapperThemeBridge.kt: Styleable & attribute reading helpersres/values/compose_theme_attrs.xml: The<declare-styleable>Core Components (
components/)AnkiTopAppBar.kt: Unified toolbar styleAnkiAlertDialog.kt: AppCompat dialog convention wrapperAnkiButton.kt: Text/filled buttons matching?colorAccentText Utilities (
text/)HtmlText.kt:AnnotatedString.fromHtml+ custom link stylesPreviews & Testing
preview/AnkiPreviews.kt:@Previewhelpers and theme variantssrc/test/: Screenshot baselines for isolated components:common semantically means "non-UI shared code." Putting UI components there is misleading. :ui-compose is unambiguous and matches Now in Android's core/designsystem convention.