I'm writing a custom view to be used inside `Andro...
# compose
j
I'm writing a custom view to be used inside
AndroidView
, but when I run my app, my custom view does not appear. I was thinking perhaps passing in null for the
root
paramater might be problematic for
LayoutInflater.from(context).finflate(R.layout.view_visualization, null, false)
. Normally, I would call
rootView
instead, but that just returns my custom view. Is there a way to instead have the root be the composable that calls this custom view?
m
Some code would be helpful here. I’ve had no issues using custom views inside of AndroidView.
I would look at the AndroidViewBinding API to do what you want.
Some code would be helpful here, but I suspect you really need to use the AndroidViewBinding API here. It supports inflation from an xml file
Something like this
Copy code
AndroidViewBinding(
   factory = { inflater, parent, attachToParent ->
     inflater.inflate(R.layout.view_visualization, parent, attachToParent)
   }
)
If you’re using view binding, it’s even sipler:
Copy code
AndroidViewBinding(factory=ViewVisualization::inflate)
j
Gotcha, I initially did try this view binding approach but encountered the error,
Error inflating class androix.fragment.app.FragmentContainerView
. Perhaps it's because I didn't insert the
FragmentContainerView
properly in my xml file? Here's the relevant code.
Copy code
@Composable
fun VizSection(onBack: () -> Unit) {
    val TAG = "VizSection"
    val fragmentContainerView = FragmentContainerView(LocalContext.current)
    Column(modifier = Modifier.fillMaxWidth()) {
        HomeNavBar(title = R.string.visualization_title, false, { onBack() }) {
            onBack()
        }
        AndroidViewBinding(FragmentVisualizationBinding::inflate) {
            Log.d(TAG, "compose: Viz Section is called")
            val vizFragment = fragmentContainerView.getFragment<VisualizationFragment>()
        }
    }
}
XML File:
Copy code
<RelativeLayout xmlns:android="<http://schemas.android.com/apk/res/android>"
    xmlns:tools="<http://schemas.android.com/tools>"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.visualization.VisualizationFragment"
    android:name="com.radgard.lara.ui.visualization.VisualizationFragment">
        <androidx.fragment.app.FragmentContainerView
            xmlns:android="<http://schemas.android.com/apk/res/android>"
            android:id="@+id/fragment_container_view"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:name="com.radgard.lara.ui.visualization.VisualizationFragment">
        </androidx.fragment.app.FragmentContainerView>


    <android.opengl.GLSurfaceView
        android:id="@+id/surfaceview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="top"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Plz work"
                android:layout_alignParentTop="true"
                android:layout_alignParentLeft="true"
                android:layout_margin="25dp"/>

    <ImageButton
        android:id="@+id/settings_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentTop="true"
        android:layout_margin="25dp"
        android:src="@drawable/ic_settings"
        android:background="@android:color/transparent"/>
</RelativeLayout>
m
I’ve never tried this approach with fragments, but i suspect it might cause issues because the compose world doesn’t really deal in fragments, so it’s kind of unclear to me how the inflater it gives you would handle it.
One thing i notice in your code is this:
Copy code
val fragmentContainerView = FragmentContainerView(LocalContext.current)
any reason that is there?
j
The stack trace points to line 7 of the XML file, not the line here. I use
fragmentContainerView
to create my fragment bc that's where I would run my ARCore-related code
m
So it sounds maybe like there’s some issue with the fragment itself. Try replacing your fragment with just a standard androidx.fragment.app.Fragment and see if it works.
I tried a basic example with an empty fragment and it worked fine.
Do you have a longer stack trace? One thing to watch out for is that your Activity has to extend FragmentActivity. In most cases in compose, people may end up extending ComponentActivity to avoid the overhead of the fragment manager.
I changed my example from FragmentActivity to ComponentActivity and this is what i got
Copy code
android.view.InflateException: Binary XML file line #12 in com.example.material3test:layout/layout_test: Binary XML file line #12 in com.example.material3test:layout/layout_test: Error inflating class androidx.fragment.app.FragmentContainerView
    Caused by: android.view.InflateException: Binary XML file line #12 in com.example.material3test:layout/layout_test: Error inflating class androidx.fragment.app.FragmentContainerView
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at android.view.LayoutInflater.createView(LayoutInflater.java:852)
Copy code
Caused by: java.lang.UnsupportedOperationException: FragmentContainerView must be within a FragmentActivity to use android:name="androidx.fragment.app.Fragment"
j
Ah, I just got the stack trace that says I need a FragmentActivity. I'm assuming you mean the MainActivity should extend a FragmentActivity? I also use Hilt in this project, and it crashes if the MainActivity is a FragmentActivity...
i
Error inflating class androix.fragment.app.FragmentContainerView
always, always, always points to another exception farther down. You'll need to include that stack trace for anyone to be able to help
460 Views