android-jetpack-composeandroid-appcompatandroid-jetpack-compose-material3

android.view.InflateException: Binary XML file line #29 in android:layout/screen_simple: Cannot add views to ComposeView


I am converting an app that is a few years old to Jetpack Compose. It's fragment based, and all of the fragments are migrated to Compose already, but I hit a problem converting the one and only Activity to use Compose. It should just be a simple Scaffold with a NavHost to receive the fragments, but it doesn't even complete onCreate with a dummy Compose layout either.

class FrameActivity : AppCompatActivity(), KoinComponent {
    lateinit var navController: NavHostController

    private val viewModel: MainNavigationViewModel by viewModel()


    override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? =
        ComposeView(context)

It is exploding while setting some transition view that I don't recall ever specifying anywhere or ever asking for. I can't tell what exactly is triggering this exception as there are no elements in my app in the stacktrace. I don't want to use whatever screen_simple.xml is.


Caused by: android.view.InflateException: Binary XML file line #29 in android:layout/screen_simple: Cannot add views to ComposeView; only Compose content is supported
Caused by: java.lang.UnsupportedOperationException: Cannot add views to ComposeView; only Compose content is supported
at androidx.compose.ui.platform.AbstractComposeView.checkAddView(ComposeView.android.kt:201)
at androidx.compose.ui.platform.AbstractComposeView.addView(ComposeView.android.kt:376)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:1139)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1096)
at android.view.LayoutInflater.inflate(LayoutInflater.java:694)
at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
at android.view.LayoutInflater.inflate(LayoutInflater.java:485)
at com.android.internal.policy.DecorView.onResourcesLoaded(DecorView.java:2207)
at com.android.internal.policy.PhoneWindow.generateLayout(PhoneWindow.java:2709)
at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2772)
at com.android.internal.policy.PhoneWindow.getDecorView(PhoneWindow.java:2154)
at android.app.ActivityTransitionState.setEnterActivityOptions(ActivityTransitionState.java:174)
at android.app.Activity.performCreate(Activity.java:8605)
at android.app.Activity.performCreate(Activity.java:8573)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1456)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3764)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8177)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

The next place to look would be the Manifest, and I tried to set the theme to various NoActionBar variants to try and stop whatever is causing the animation transition to happen. I even tried omitting the theme element from here altogether.

<application
        android:allowBackup="true"
       ...
        android:theme="@style/Theme.Material3.Light.NoActionBar">
        <activity
            android:name=".activity.FrameActivity"
            android:exported="true"
            android:theme="@style/Theme.Material3.Light.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

I also tried to replace AppCompatActivity with ComponentActivity but this still produced the same exception.

class FrameActivity : ComponentActivity(), KoinComponent {

And then finally I tried sneaking in overridePendingTransition() to onCreate() but this didn't change the exception either. I can't seem to get rid of the exception and I don't want to be stuck with a part of the app missing the MaterialTheme being used everywhere else.


Solution

  • Calling Compose from an Activity should be as simple as this:

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            enableEdgeToEdge()
            setContent {
                MyApplicationTheme {
                    Surface {
                        MainScreen()
                    }
                }
            }
        }
    }
    
    @Composable
    fun MainScreen(
        viewModel: MainNavigationViewModel = viewModel()
    ) {
        val navController = rememberNavController()
    
        Scaffold(
            topBar = {
                CenterAlignedTopAppBar(title = { Text("My Application") })
            }
        ) { padding ->
            NavHost(
                navController = navController,
                startDestination = "screenA",
                modifier = Modifier.padding(padding)
            ) {
                composable("screenA") { /** Your AndroidFragment or Composable **/ }
                composable("screenB") { /** Your AndroidFragment or Composable **/ }
            }
        }
    }
    

    In order to obtain a MyApplicationTheme, head over to the Material3 Theme Builder and enter the main colors of your current themes.xml there. Then you can export a Theme.kt file that is compatible with Compose.

    Also ensure all dependencies are present as described in the Compose Migration Codelab.