Skip to main content

Released documentation snapshot. This immutable manual describes viewcompose-overlay-android:0.1.0-alpha03 from source revision 2d7c8561. For current guidance, open the current module catalog.

Overlay Android

viewcompose-overlay-android is the optional Android presentation backend for ViewCompose dialogs, anchored popups, modal bottom sheets, snackbars, and toasts. The declarative overlay protocol, DSL, queue policy, positioning model, and nested surface sessions live in viewcompose-widget-core; this artifact maps those contracts to Android and Material platform windows.

Artifact and stability​

dependencies {
implementation("com.viewcompose:viewcompose-overlay-android:0.1.0-alpha01")
}
  • Stability: Alpha. Window presentation and Material integration may evolve between alphas.
  • Platform: Android library with a minimum SDK inherited from the repository Android policy.
  • UI contract and widget core are exposed transitively because their environment, builder, and overlay contracts appear in public APIs. Host Android remains an implementation dependency, and core rendering does not depend on this artifact.
  • Omitting the artifact keeps the renderer operational: overlay requests use the core no-op host and emit a one-time diagnostic message instead of failing application startup.

Installation and discovery​

The artifact registers AndroidOverlayHostFactoryProvider through Java ServiceLoader. Normal ViewCompose hosts call OverlayHostDefaults.androidOrNoOp(rootView), so adding the dependency is enough; no Application initialization or manifest component is required.

Custom render hosts can construct AndroidOverlayHost(rootView) explicitly and install it with ProvideOverlayHost. Create one host per attached render root, clear each render session during teardown, and do not retain the host beyond the root View's window lifetime.

All commits, dismissal calls, and platform callbacks run on the Android main thread.

Session ownership and reconciliation​

Every overlay identity combines a render-session ID with the DSL request key. A commit is the complete desired request set for one session:

  • adding a key creates its platform handle;
  • changing a same-key request updates the existing handle when that overlay type supports updates;
  • omitting a previous key dismisses only that session's handle;
  • clearing a session dismisses its surfaces and removes its pending transient feedback;
  • requests from another session are never removed as a side effect.

Dialog, popup, and bottom-sheet content is rendered by a nested OverlaySurfaceSession. The session captures ViewCompose locals when content is declared and owns its renderer until the platform handle is dismissed. Programmatic host cleanup suppresses onDismissRequest; only user or platform window dismissal asks application state to remove the declarative request.

Dialogs​

Dialogs use a transparent Android Dialog and a nested ViewCompose surface. Dismiss-on-Back and dismiss-on-outside-touch are mapped to platform cancelability. Logical top, center, and bottom positions map to window gravity, and scrim opacity is clamped to Android's 0f..1f range.

Changing content, position, dismissal policy, or scrim opacity under the same key updates the existing window and render session. Removing the request disposes the nested session before closing the window.

Anchored popups​

Popup requests resolve anchorId against the current native View tree. The renderer marks the matching DSL anchor with an internal tag; the Android backend finds that View and calculates physical coordinates from anchor bounds, popup size, visible window bounds, layout direction, logical alignment, offsets, margin, and overflow policy.

The handle observes attachment, global layout, and scrolling. It remeasures after content changes and updates PopupWindow only when position or size actually changes. If an anchor temporarily disappears or has no geometry, the popup hides without reporting dismissal and reappears after the anchor returns. This covers lazy-item recycling, scrolling, IME changes, and window resizing.

Use stable, unique anchor IDs within one render root. A depth-first search selects the first matching native View, so duplicate IDs make placement depend on View hierarchy order.

Modal sheets use Material BottomSheetDialog. Same-key updates preserve the dialog and nested surface while applying dismissal policy, scrim opacity, expansion policy, and content changes.

skipPartiallyExpanded maps to an immediately expanded Material behavior with the collapsed intermediate state skipped. An explicit navigation-bar color is applied to the sheet window. Without an override, the backend restores the dialog default and keeps Android's contrast enforcement.

Snackbar and toast queues​

Widget core owns the shared snackbar/toast queue; this module supplies only platform presenters. Queue policies, replacement, dropping, and session removal therefore behave identically in tests and on Android.

Material Snackbar provides a real terminal callback. Action clicks invoke the application action, then the platform callback reports Action, Timeout, Gesture, Replaced, or a generic platform reason to the queue. An explicit framework dismissal reason wins over Material's callback event.

Android Toast has no reliable completion callback. The backend uses application context and a main- looper timeout approximating the platform short or long duration. This keeps the queue moving without retaining an Activity, but timeout completion should not be treated as a frame-accurate signal that a system-rendered toast has vanished.

Resource and lifecycle boundaries​

  • Dialogs, popups, and bottom sheets retain their root View context because they belong to its window; clearing their render session releases the platform window and nested renderer.
  • Toasts retain only application context.
  • Popup attach, layout, and scroll listeners are removed when their handle is dismissed.
  • A hidden popup remains logically active while waiting for its anchor; removal or session cleanup still disposes it immediately.
  • The backend intentionally owns no Activity, Fragment, ViewModel, or saved-state namespace.

Testing and custom hosts​

Most application tests should exercise declarative requests through the widget-core recording hosts and queue snapshots. Use Robolectric or device tests when validating Android window flags, Material callbacks, popup geometry, or system-bar appearance.

Custom platform backends can implement the widget-core presenter and handle interfaces without depending on this artifact. Keep the same session isolation, idempotent update, single terminal dismissal, and resource-disposal guarantees.

The complete generated reference is available in the viewcompose-overlay-android API tree.

Compatibility notes​

The 0.1.0-alpha01 line establishes optional service-provider discovery, session-isolated platform handles, nested surface rendering, anchored popup recovery, Material bottom sheets and snackbars, and application-context toasts. Treat Android window objects as backend implementation details and keep application state authoritative through declarative overlay requests.