Closed Iridescentangle closed 2 years ago
疑,你是怎么使用的,Compose 这个东西不是理论上可以内嵌到任何的 ViewGroup 里面吗?
https://developer.android.google.cn/jetpack/compose/interop/adding#reuse-view
假设我们要在应用中将用户问候文本迁移到 Jetpack Compose。我们可以在 XML 布局中添加以下内容: 为了将其迁移到 Compose,我们可以将 View 替换为保留了相同布局参数和 id 的 ComposeView: 然后,在使用了该 XML 布局的 Activity 或 Fragment 中,我们可以获取 ComposeView,并调用 setContent 方法,以向其中添加 Compose 内容:
我是按照这种方式来做的
class ComposeScene : Scene() {
private lateinit var composeView : ComposeView
override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
composeView = ComposeView(requireSceneContext())
return composeView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
composeView.setContent {
CardTheme {
ProvideWindowInsets {
val systemUiController = rememberSystemUiController()
val darkIcons = MaterialTheme.colors.isLight
SideEffect {
systemUiController.setSystemBarsColor(Color.Transparent, darkIcons = darkIcons)
}
val navController = rememberNavController()
// val navigationActions = remember(navController){
//
// }
Greeting()
}
}
}
}
@Composable
private fun Greeting() {
Text(
text = "我是测试文字",
modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp)
)
}
}
在你的首页的 Activity 的 onCreate 里面补充这段代码
ViewTreeLifecycleOwner.set(window.decorView, this)
ViewTreeViewModelStoreOwner.set(window.decorView, this)
ViewTreeSavedStateRegistryOwner.set(window.decorView, this)
头疼啊,公司内部的 androidx 版本普通很旧,所以这个框架也不好直接升级 androidx 的依赖
还有一种做法,我感觉这种更合适
import android.view.View
import androidx.compose.runtime.MonotonicFrameClock
import androidx.compose.runtime.PausableMonotonicFrameClock
import androidx.compose.runtime.Recomposer
import androidx.compose.ui.platform.AndroidUiDispatcher
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.bytedance.scene.Scene
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.launch
import kotlin.coroutines.EmptyCoroutineContext
fun Scene.createLifecycleAwareViewTreeRecomposer(): Recomposer {
val currentThreadContext = AndroidUiDispatcher.CurrentThread
val pausableClock = currentThreadContext[MonotonicFrameClock]?.let {
PausableMonotonicFrameClock(it).apply { pause() }
}
val contextWithClock = currentThreadContext + (pausableClock ?: EmptyCoroutineContext)
val recomposer = Recomposer(contextWithClock)
val runRecomposeScope = CoroutineScope(contextWithClock)
val viewTreeLifecycleOwner = this
// Removing the view holding the ViewTreeRecomposer means we may never be reattached again.
// Since this factory function is used to create a new recomposer for each invocation and
// doesn't reuse a single instance like other factories might, shut it down whenever it
// becomes detached. This can easily happen as part of setting a new content view.
this.view.addOnAttachStateChangeListener(
object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View?) {}
override fun onViewDetachedFromWindow(v: View?) {
this@createLifecycleAwareViewTreeRecomposer.view.removeOnAttachStateChangeListener(this)
recomposer.cancel()
}
}
)
viewTreeLifecycleOwner.lifecycle.addObserver(
object : LifecycleEventObserver {
override fun onStateChanged(lifecycleOwner: LifecycleOwner, event: Lifecycle.Event) {
val self = this
when (event) {
Lifecycle.Event.ON_CREATE ->
// Undispatched launch since we've configured this scope
// to be on the UI thread
runRecomposeScope.launch(start = CoroutineStart.UNDISPATCHED) {
try {
recomposer.runRecomposeAndApplyChanges()
} finally {
// If runRecomposeAndApplyChanges returns or this coroutine is
// cancelled it means we no longer care about this lifecycle.
// Clean up the dangling references tied to this observer.
lifecycleOwner.lifecycle.removeObserver(self)
}
}
Lifecycle.Event.ON_START -> pausableClock?.resume()
Lifecycle.Event.ON_STOP -> pausableClock?.pause()
Lifecycle.Event.ON_DESTROY -> {
recomposer.cancel()
}
Lifecycle.Event.ON_PAUSE -> {
// Nothing
}
Lifecycle.Event.ON_RESUME -> {
// Nothing
}
Lifecycle.Event.ON_ANY -> {
// Nothing
}
}
}
}
)
return recomposer
}
然后你的 Scene,补充 composeView.setParentCompositionContext(createLifecycleAwareViewTreeRecomposer())
class ComposeScene : Scene() {
private lateinit var composeView : ComposeView
override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {
composeView = ComposeView(requireSceneContext())
return composeView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
ViewTreeLifecycleOwner.set(this.view, this)
ViewTreeViewModelStoreOwner.set(this.view, this)
ViewTreeSavedStateRegistryOwner.set(this.view, fragmentActivity())
composeView.setParentCompositionContext(createLifecycleAwareViewTreeRecomposer())
composeView.setContent {
CardTheme {
ProvideWindowInsets {
val systemUiController = rememberSystemUiController()
val darkIcons = MaterialTheme.colors.isLight
SideEffect {
systemUiController.setSystemBarsColor(Color.Transparent, darkIcons = darkIcons)
}
val navController = rememberNavController()
// val navigationActions = remember(navController){
//
// }
Greeting()
}
}
}
}
@Composable
private fun Greeting() {
Text(
text = "我是测试文字",
modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp)
)
}
}
好的...我试一哈,多谢大佬指点ღ( ´・ᴗ・` )
@qii 是可以的,多谢!!
有考虑兼容Compose嘛(╹▽╹)尝试在Scene中嵌入ComposeView报错