Reputation: 5925
In my activity class whose layout set with xml, i want to show a dialog. ın this dialog i want to use Jetpack Compsose. Is this possible ? My codes are as the following and i get the following crash :
java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from android.widget.RelativeLayout{910e78c V.E...... ......I. 0,0-0,0}
Here is my activity class :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<android.widget.Button>(R.id.buttonPuppyInfo)
button.text = "Open dialog"
val dialog = Dialog(this@MainActivity)
dialog.setContentView(R.layout.custom_dialog);
val composeView = dialog.findViewById<ComposeView>(R.id.composeView)
composeView.setContent {
Button(
onClick = {
// Change the state to close the dialog
//setShowDialog(false)
},
) {
Text("Superrr")
}
}
button.setOnClickListener {
dialog.show();
}
}
}
Below is my custom_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:text="hello world!"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.compose.ui.platform.ComposeView
android:id="@+id/composeView"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_below="@id/textView">
</androidx.compose.ui.platform.ComposeView>
</RelativeLayout>
Below is my dependencies const val composeVersion = "1.0.2"
implementation("androidx.compose.ui:ui:${Versions.composeVersion}")
implementation("androidx.compose.ui:ui-tooling:${Versions.composeVersion}")
implementation("androidx.compose.material:material:${Versions.composeVersion}")
implementation("androidx.compose.material:material-icons-extended:${Versions.composeVersion}")
implementation("androidx.compose.runtime:runtime:${Versions.composeVersion}")
implementation("androidx.activity:activity-compose:1.3.1")
implementation("androidx.navigation:navigation-compose:2.4.0-alpha08")
implementation("org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlinVersion}")
implementation("androidx.core:core-ktx:1.6.0")
implementation("androidx.appcompat:appcompat:1.4.0-alpha03")
implementation("com.google.android.material:material:1.4.0")
Upvotes: 12
Views: 5066
Reputation: 345
Same question as https://stackoverflow.com/posts/77523002/edit
Currently AppCompatDialog which extends ComponentDialog had a LifeCycleOwner bug because it didn't forward setContent call to it's super, causing LifeCycleOwner missing https://issuetracker.google.com/issues/261314581
You can inject it yourself by doing this before setConentView()
fun injectViewTree() {
try {
window!!.decorView.setViewTreeLifecycleOwner(this)
window!!.decorView.setViewTreeOnBackPressedDispatcherOwner(this)
window!!.decorView.setViewTreeSavedStateRegistryOwner(ownerActivity as ComponentActivity)
window!!.decorView.setViewTreeViewModelStoreOwner(ownerActivity as ComponentActivity)
} catch (e: Exception) {
Log.e("BaseMvpDialogExt", "injectViewTree", e)
}
}
Then call in your custom dialog, call it before setContent
injectViewTree(this);
setContentView(viewDataBinding.getRoot());
Upvotes: -1
Reputation: 5925
After thinking more, I believed that this idea is bad, so i didn't waste time on this unnecessary and wrong idea. If your activity is xml based do your dialog with xml. If it's based on compose than do it with compose. That's my inference.
Upvotes: -1
Reputation: 1975
I'm not sure about using Compose with the old android UI Dialog, I think you should use compositionStrategy which tells compose to bound to an existing lifecycle.
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
Also what I did in my current app is using Compose Dialog with the old activity/fragment XML.
Fragment/Activity XML:
<FrameLayout>
// here my activity/fragment xml ui
<Constraintlayout/>
// here I will call the Compose Dialog
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
In the Activity/Fragment:
composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
var openDialog by remember { mutableStateOf(true) }
Theme {
if(openDialog){
AlertDialog(...)
}
}
}
}
Upvotes: 3