Skip to main content
Donovan LaDuke - Developer

Using XML Views in Compose


Featured in Android Weekly Issue 619

The last article covered using Compose views in an existing XML view, but what happens when the opposite is needed? This is still a common scenario for both apps that have existing XML views that are not yet implemented in Compose but also for many Compose apps that need to use views from libraries that have not yet added Compose support like CameraX. Much like the effort to add Compose to XML, this process is ultimately painless once the basics are understood.

XML Views in Compose #

Creating an XML View in Compose is actually the same as creating a view programmatically in an Activity or Fragment. The only difference is that the new View is created inside of an AndroidView composable. The XML view is created in the factory parameter which provides the context to the receiver. From there, pass any parameters as needed into the view. These parameters can be handled externally just like any other composable's parameters. Here is a code example of a compose wrapper for the CameraX PreviewView.

fun CameraXPreviewView(
  cameraController: CameraController, 
  modifier: Modifer = Modifier,
) {
  AndroidView(
    factory = { context -> 
      PreviewView(context).apply {
        layoutParams = ViewGroup.LayoutParams(
          MATCH_PARENT, 
          MATCH_PARENT,
        )
        controller = cameraController
      }
    }, 
    modifier = modifier,
  )
}

Responding to Compose State Updates #

If data needs to be pulled out of a view and made available in compose, the update parameter in the AndroidView can be used to update a view based on changes to compose state. Here is a simple example of implementing a clear button in Compose that updates the content of an EditText in an AndroidView.

var clear by remember { mutableStateOf(false) }

Column {
  AndroidView(
    factory = { context ->
      EditText(context).apply {
        layoutParams = ViewGroup.LayoutParams(
          MATCH_PARENT,
          WRAP_CONTENT,
        )
      }
    },
    update = { view ->
      if (clear) {
        view.text.clear()
        clear = false
      }
    }
  )
  Button(onClick = { clear = true }) {
    Text("Clear")
  }
}

Conclusion #

Setting up a view in Compose is just that simple. If the view in question is more complex it could require additional configuration or using the update parameter in the AndroidView composable to get information about the state of the view on recomposition. Regardless, to use views in Compose until they are ready to be updated to Compose or if they are just too complex to rewrite at this time is a very managable effort. Until next time, thanks!

Did you find this content helpful?

Please share this post and be sure to subscribe to the RSS feed to be notified of all future articles!

Want to go above and beyond? Help me out by sending me $1 on Ko-fi. It goes a long way in helping run this site and keeping it advertisement free. Thank you in advance!

Buy me a Coffee on Ko-fi