Tencent/QMUI_Android · error · RuntimeException

View is not attached to Activity

Error message

View is not attached to Activity

What it means

ActivityHostModalProvider.provide() walks from the given View up to its rootView and looks up the window's android.R.id.content FrameLayout. If that lookup returns null, the view hierarchy is not an Activity window (e.g. the view lives in a Dialog, or was never attached), so a RuntimeException is thrown because there is no Activity content parent to host the modal.

Source

Thrown at compose/src/main/java/com/qmuiteam/compose/modal/QMUIModal.kt:107

    fun doOnShow(listener: Action): QMUIModal
    fun doOnDismiss(listener: Action): QMUIModal
    fun removeOnShowAction(listener: Action): QMUIModal
    fun removeOnDismissAction(listener: Action): QMUIModal

    fun interface Action {
        fun invoke(modal: QMUIModal)
    }
}

fun interface ModalHostProvider {
    fun provide(view: View): Pair<FrameLayout, OnBackPressedDispatcher>
}

class ActivityHostModalProvider : ModalHostProvider {
    override fun provide(view: View): Pair<FrameLayout, OnBackPressedDispatcher> {
        val contentLayout =
            view.rootView.findViewById<FrameLayout>(Window.ID_ANDROID_CONTENT) ?: throw RuntimeException("View is not attached to Activity")
        val activity = contentLayout.context as? AppCompatActivity ?: throw RuntimeException("view's rootView's context is not AppCompatActivity")
        return contentLayout to activity.onBackPressedDispatcher
    }
}

val DefaultModalHostProvider = ActivityHostModalProvider()

fun View.qmuiModal(
    mask: Color = DefaultMaskColor,
    systemCancellable: Boolean = true,
    maskTouchBehavior: MaskTouchBehavior = MaskTouchBehavior.dismiss,
    uniqueId: Long = SystemClock.elapsedRealtimeNanos(),
    modalHostProvider: ModalHostProvider = DefaultModalHostProvider,
    enter: EnterTransition = fadeIn(tween(), 0f),
    exit: ExitTransition = fadeOut(tween(), 0f),
    content: @Composable AnimatedVisibilityScope.(QMUIModal) -> Unit
): QMUIModal {
    if (!isAttachedToWindow) {

View on GitHub (pinned to 026e7d4866)

Solutions

  1. Ensure the view passed to the modal API is attached to a normal Activity window (check view.isAttachedToWindow first).
  2. Pass a view that is a descendant of the Activity's content view, not one hosted in a Dialog/PopupWindow.
  3. Supply a custom ModalHostProvider that resolves the FrameLayout and OnBackPressedDispatcher for your non-standard host.
  4. Defer showing the modal until after the Activity content is laid out (e.g. view.post { }).

Example fix

// before
myDialogContentView.qmuiDialog { ... } // throws: not in Activity window
// after
requireNotNull(activity.findViewById<ViewGroup>(android.R.id.content))
activity.contentView.qmuiDialog { ... }
Defensive patterns

Strategy: validation

Validate before calling

fun isHostedInActivity(view: View): Boolean =
  view.isAttachedToWindow && view.rootView.findViewById<ViewGroup>(android.R.id.content) != null

Type guard

fun View.findActivityContent(): FrameLayout? = rootView.findViewById(Window.ID_ANDROID_CONTENT)

Try / catch

try { view.qmuiDialog { ... } } catch (e: RuntimeException) { Log.e(TAG, "modal host unavailable", e) }

Prevention

When it happens

Trigger: Calling qmuiModal/qmuiStillModal (or qmuiBottomSheet/qmuiDialog/qmuiToast) with a view whose rootView does not contain Window.ID_ANDROID_CONTENT — i.e. the view is attached to a non-Activity window (Dialog, PopupWindow, overlay) or the rootView lacks the content frame.

Common situations: Showing a modal from a Dialog or floating window context; view not yet attached so rootView is a temporary parent; using the modal inside a custom presentation or Compose-in-Dialog host.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Tencent/QMUI_Android@026e7d4866 (2026-09-06). Data as JSON: /api/errors/79582a25dc433dca. Report an issue: GitHub.