Vous pouvez inclure une hiérarchie des vues Android dans une interface utilisateur Compose. Cette approche est particulièrement utile si vous souhaitez utiliser des éléments d'interface utilisateur qui ne sont pas encore disponibles dans Compose, comme AdView
.
Cela vous permet également de réutiliser des vues personnalisées.
Pour inclure un élément ou une hiérarchie de vues, utilisez le composable AndroidView
. AndroidView
reçoit un lambda qui renvoie une View
. AndroidView
fournit également un rappel update
, qui est appelé lorsque la vue est gonflée. AndroidView
se recompose chaque fois qu'une lecture State
du rappel change. Comme de nombreux autres composables intégrés, AndroidView
utilise un paramètre Modifier
qui peut servir, par exemple, à définir sa position dans le composable parent.
@Composable fun CustomView() { var selectedItem by remember { mutableStateOf(0) } // Adds view to Compose AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> // Creates view MyView(context).apply { // Sets up listeners for View -> Compose communication setOnClickListener { selectedItem = 1 } } }, update = { view -> // View's been inflated or state read in this block has been updated // Add logic here if necessary // As selectedItem is read here, AndroidView will recompose // whenever the state changes // Example of Compose -> View communication view.selectedItem = selectedItem } ) } @Composable fun ContentExample() { Column(Modifier.fillMaxSize()) { Text("Look at this CustomView!") CustomView() } }
AndroidView
avec liaison de vue
Pour intégrer une mise en page XML, utilisez l'API AndroidViewBinding
fournie par la bibliothèque androidx.compose.ui:ui-viewbinding
. Pour ce faire, votre projet doit activer la liaison de vue.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
dans les listes différées
Si vous utilisez un AndroidView
dans une liste paresseuse (LazyColumn
, LazyRow
, Pager
, etc.), envisagez d'utiliser la surcharge AndroidView
introduite dans la version 1.4.0-rc01. Cette surcharge permet à Compose de réutiliser l'instance View
sous-jacente lorsque la composition contenante est réutilisée, comme c'est le cas pour les listes différées.
Cette surcharge de AndroidView
ajoute deux paramètres supplémentaires:
onReset
: rappel appelé pour signaler que l'View
est sur le point d'être réutilisé. Cette valeur ne doit pas être nulle pour permettre la réutilisation de la vue.onRelease
(facultatif) : rappel appelé pour signaler que leView
a quitté la composition et ne sera plus réutilisé.
@OptIn(ExperimentalComposeUiApi::class) @Composable fun AndroidViewInLazyList() { LazyColumn { items(100) { index -> AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> MyView(context) }, update = { view -> view.selectedItem = index }, onReset = { view -> view.clear() } ) } } }
Fragments dans Compose
Utilisez le composable AndroidViewBinding
pour ajouter un Fragment
dans Compose.
AndroidViewBinding
offre une gestion spécifique au fragment, comme la suppression du fragment lorsque le composable quitte la composition.
Pour ce faire, gonflez le code XML d'un conteneur FragmentContainerView
pour en faire le conteneur de votre Fragment
.
Par exemple, si vous avez défini my_fragment_layout.xml
, vous pouvez utiliser un code comme celui-ci tout en remplaçant l'attribut XML android:name
par le nom de classe de Fragment
:
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.compose.snippets.interop.MyFragment" />
Pour gonfler ce fragment dans Compose, procédez comme suit :
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Si vous devez utiliser plusieurs fragments dans la même mise en page, assurez-vous d'avoir défini un ID unique pour chaque FragmentContainerView
.
Appeler le framework Android à partir de Compose
Compose fonctionne dans les classes du framework Android. Par exemple, il est hébergé sur les classes de vues Android, comme Activity
ou Fragment
, et peut utiliser des classes du framework Android comme Context
, les ressources système, Service
ou encore BroadcastReceiver
.
Pour en savoir plus sur les ressources système, consultez la section Ressources dans Compose.
Compositions locales
Les classes CompositionLocal
permettent de transmettre des données implicitement via des fonctions modulables. Elles sont généralement accompagnées d'une valeur dans un nœud spécifique de l'arborescence de l'interface utilisateur. Cette valeur peut être utilisée par ses descendants composables sans déclarer le CompositionLocal
en tant que paramètre dans la fonction modulable.
CompositionLocal
permet de propager des valeurs pour les types de frameworks Android dans Compose, tels que Context
, Configuration
ou View
, dans lesquels le code Compose est hébergé avec les éléments LocalContext
, LocalConfiguration
ou LocalView
correspondants.
Notez que les classes CompositionLocal
sont précédées de Local
pour une meilleure visibilité avec la saisie semi-automatique dans l'IDE.
Pour accéder à la valeur actuelle de CompositionLocal
, utilisez sa propriété current
. Par exemple, le code ci-dessous affiche un toast en fournissant le LocalContext.current
dans la méthode Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Pour un exemple plus complet, consultez la section Étude de cas : BroadcastReceivers à la fin de ce document.
Autres interactions
Si aucun utilitaire n'est défini pour l'interaction dont vous avez besoin, nous vous recommandons de suivre les consignes générales de Compose : le flux de données descend, le flux d'événements monte. Plus de détails sont disponibles dans Raisonnement dans Compose. Par exemple, ce composable lance une autre activité :
class OtherInteractionsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // get data from savedInstanceState setContent { MaterialTheme { ExampleComposable(data, onButtonClick = { startActivity(Intent(this, MyActivity::class.java)) }) } } } } @Composable fun ExampleComposable(data: DataExample, onButtonClick: () -> Unit) { Button(onClick = onButtonClick) { Text(data.title) } }
Étude de cas : broadcast receivers
Pour obtenir un exemple plus concret des fonctionnalités que vous pouvez migrer ou implémenter dans ComposeCompositionLocal
, ainsi que des effets secondaires, imaginons qu'un BroadcastReceiver
doit être enregistré à partir d'une fonction modulable.
La solution utilise LocalContext
pour utiliser le contexte actuel, ainsi que les effets secondaires rememberUpdatedState
et DisposableEffect
.
@Composable fun SystemBroadcastReceiver( systemAction: String, onSystemEvent: (intent: Intent?) -> Unit ) { // Grab the current context in this part of the UI tree val context = LocalContext.current // Safely use the latest onSystemEvent lambda passed to the function val currentOnSystemEvent by rememberUpdatedState(onSystemEvent) // If either context or systemAction changes, unregister and register again DisposableEffect(context, systemAction) { val intentFilter = IntentFilter(systemAction) val broadcast = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { currentOnSystemEvent(intent) } } context.registerReceiver(broadcast, intentFilter) // When the effect leaves the Composition, remove the callback onDispose { context.unregisterReceiver(broadcast) } } } @Composable fun HomeScreen() { SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus -> val isCharging = /* Get from batteryStatus ... */ true /* Do something if the device is charging */ } /* Rest of the HomeScreen */ }
Étapes suivantes
Maintenant que vous connaissez les API d'interopérabilité lorsque vous utilisez Compose dans les vues et inversement, consultez la page Autres considérations pour en savoir plus.
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Autres points à prendre en compte
- Effets secondaires dans Compose
- Données à champ d'application local avec CompositionLocal