android - 将 ComposeView 添加到 PopupWindow 的 contentView 崩溃

标签 android android-lifecycle popupwindow android-jetpack-compose android-popupwindow

我正在尝试显示 PopupWindow来自 Fragment ,然后添加 ComposableView到弹出窗口contentView ,它崩溃是因为 ViewTreeLifecycleOwner未找到 PopupDecorView$PopupDecorView .
我尝试过的事情:

  • 使用 PopupWindowCompat显示弹出窗口。
  • Fragment 的多个库版本(1.3.4 和 1.4.0-alpha1)。
  • Activity我使用的版本是:1.3.0-alpha08。
  • 手动设置 contentView 的生命周期所有者和 ComposeView .

  • 来电:
    添加 ComposeViewcontentView :
     contentWindow.contentView.addView(
                    AdaptiveCardistRender.adaptiveCardistResponseView(
                        contentWindow.contentView.context,
                        response
                    )
                )
    
    显示弹出窗口:
    PopupWindowCompat.showAsDropDown(
                    popupWindow,
                    anchor,
                    0,
                    startVerticalOffset,
                    Gravity.NO_GRAVITY
                )
    
    PopupWindow 上设置生命周期:
    class ExtensionsPopupWindow(
        val contentView: ScrollView,
        width: Int,
        height: Int,
        lifecycleOwner: LifecycleOwner,
        savedStateRegistryOwner: SavedStateRegistryOwner,
    ) : PopupWindow(contentView, width, height, true) {
    
        init {
            ViewTreeLifecycleOwner.set(contentView, lifecycleOwner)
            ViewTreeSavedStateRegistryOwner.set(contentView, savedStateRegistryOwner)
        }
    
    堆栈跟踪:
        java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from android.widget.PopupWindow$PopupDecorView{9dfea2f V.E...... R.....I. 0,0-0,0}
            at androidx.compose.ui.platform.WindowRecomposer_androidKt.createLifecycleAwareViewTreeRecomposer(WindowRecomposer.android.kt:242)
            at androidx.compose.ui.platform.WindowRecomposer_androidKt.access$createLifecycleAwareViewTreeRecomposer(WindowRecomposer.android.kt:1)
            at androidx.compose.ui.platform.WindowRecomposerFactory$Companion$LifecycleAware$1.createRecomposer(WindowRecomposer.android.kt:98)
            at androidx.compose.ui.platform.WindowRecomposerPolicy.createAndInstallWindowRecomposer$ui_release(WindowRecomposer.android.kt:153)
            at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer.android.kt:228)
            at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(ComposeView.android.kt:200)
            at androidx.compose.ui.platform.AbstractComposeView.onAttachedToWindow(ComposeView.android.kt:235)
            at android.view.View.dispatchAttachedToWindow(View.java:20665)
            at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3493)
            at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3500)
            at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3500)
            at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3500)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2544)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2057)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8501)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1005)
            at android.view.Choreographer.doCallbacks(Choreographer.java:826)
            at android.view.Choreographer.doFrame(Choreographer.java:761)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:990)
            at android.os.Handler.handleCallback(Handler.java:938)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loopOnce(Looper.java:201)
            at android.os.Looper.loop(Looper.java:288)
            at android.app.ActivityThread.main(ActivityThread.java:7727)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
    

    最佳答案

    默认情况下,PopupWindow 不能与 compose 一起使用。
    compose 需要做一些设置才能找到:

  • 内容子
  • ViewTreeLifecycleOwner,
  • ViewTreeSavedStateRegistryOwner。

  • 这是一个示例,说明如何在弹出窗口内使用撰写 View 显示来自撰写的弹出窗口。
    (最重要的部分是parentView)
    val composeView = ComposeView(LocalContext.current).apply {
        setContent {
            // your composables
        }
    }
    val parentView = FrameLayout(LocalContext.current).apply {
        // Help compose to find View.contentChild
        id = android.R.id.content
        // Help compose to find ViewTreeLifecycleOwner
        ViewTreeLifecycleOwner.set(this, LocalLifecycleOwner.current)
        // Help compose to find ViewTreeSavedStateRegistryOwner
        ViewTreeSavedStateRegistryOwner.set(this, LocalSavedStateRegistryOwner.current)
    
        layoutParams = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
        )
        addView(composeView)
    
    }
    val popupWindow = PopupWindow(
        parentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
    )
    
    popupWindow.showAtLocation(LocalView.current, Gravity.CENTER, 0, 0)
    
    DisposableEffect(Unit) {
        onDispose {
            popupWindow.dismiss()
        }
    }
    
    如果您从 Activity 中执行此操作,请替换 LocalLifecycleOwner.current , LocalSavedStateRegistryOwner.currentLocalContext.current通过你的 Activity 。

    关于android - 将 ComposeView 添加到 PopupWindow 的 contentView 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67714035/

    相关文章:

    Android 简单的微调器项目

    多次调用 Android LiveData observe

    javascript - 在 Asp .Net 中多次显示弹出消息

    android - 为 popUpWindow 设置样式

    java - IOException : Permission Denied

    android - 应用程序配置错误对不起,myapp未获批准在App Center中显示。在android app share中

    android - 离线drm。使用 exoplayer 获取离线安全内容

    java - Android socket.close() 导致 "the system call was canceled"?

    Android Activity 在使用暗模式时被实例化两次

    android - 在弹出窗口中显示 ListView - Android