在Android的WindowManager中添加ComposeView的流程及注意事项
流程
总体跟普通的View一样设置窗口参数再用addView添加到WIndowManager中
private val wm by lazy { MobilePlatformPlugin.applicationContext.getSystemService(WINDOW_SERVICE) as WindowManager }
fun showPopWindow(context: Context) {
val params = WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, // 宽度
WindowManager.LayoutParams.MATCH_PARENT, // 高度
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // 窗口类型 TODO: //API Level
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, // 窗口标志
PixelFormat.TRANSLUCENT // 像素格式
)
composeView = ComposeView(context = context).apply {
setContent {
PopWindowView()
}
}
lifecycleOwner = MyComposeViewLifecycleOwner().also {
it.onCreate() // 注意
it.attachToDecorView(composeView)
}
wm.addView(composeView, params)
lifecycleOwner?.onStart()
lifecycleOwner?.onResume()
}
不过ComposeView需要有LifeCycleOwner的支持,不然运行会崩溃,所以需要自定义一个LifeCycleOwner,完全照抄下面这个即可,这里我也是抄的哈哈
private class MyComposeViewLifecycleOwner : LifecycleOwner, ViewModelStoreOwner,
SavedStateRegistryOwner {
private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
private val savedStateRegistryController = SavedStateRegistryController.create(this)
private val store = ViewModelStore()
override val lifecycle: Lifecycle
get() = lifecycleRegistry
override val savedStateRegistry: SavedStateRegistry
get() = savedStateRegistryController.savedStateRegistry
override val viewModelStore: ViewModelStore
get() = store
fun onCreate() {
savedStateRegistryController.performRestore(null)
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
fun onStart() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
fun onResume() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
fun onPause() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
fun onStop() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
fun onDestroy() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
store.clear()
}
/**
* Compose uses the Window's decor view to locate the
* Lifecycle/ViewModel/SavedStateRegistry owners.
* Therefore, we need to set this class as the "owner" for the decor view.
*/
fun attachToDecorView(decorView: View?) {
decorView?.let {
it.setViewTreeViewModelStoreOwner(this)
it.setViewTreeLifecycleOwner(this)
it.setViewTreeSavedStateRegistryOwner(this)
} ?: return
}
}
注意事项
这里需要注意一个非常关键的点,有一些资料只执行了LifeCycleOwner的create事件,只执行create事件可能会导致Compose的状态监听失效,所以最后一定要模拟start和resume事件,一定要在addView后添加
lifecycleOwner?.onStart()
lifecycleOwner?.onResume()
这个坑有点大,研究了挺久才发现,所以放出来希望能帮助到遇到同样问题的人们。
销毁
最后关闭悬浮窗也记得执行一下pause,stop,destroy流程
fun closePopWindow() {
if (composeView?.isAttachedToWindow != true) return
wm.removeView(composeView)
composeView = null
lifecycleOwner?.onPause()
lifecycleOwner?.onStop()
lifecycleOwner?.onDestroy()
lifecycleOwner = null
}