Puoi includere una gerarchia di oggetti View Android in un'interfaccia utente di Compose. Questo approccio è
particolarmente utile se vuoi utilizzare elementi dell'interfaccia utente non ancora disponibili in
Compose, come
AdView.
Questo approccio ti consente anche di riutilizzare le visualizzazioni personalizzate che potresti aver progettato.
Per includere un elemento o una gerarchia di visualizzazioni, utilizza il AndroidView
componibile. A AndroidView viene passata una lambda che restituisce un
View. AndroidView fornisce anche un callback update che viene chiamato quando la visualizzazione viene espansa. AndroidView viene ricomposto ogni volta che cambia uno State letto all'interno del callback. AndroidView, come molti altri componibili integrati, accetta un parametro Modifier che può essere utilizzato, ad esempio, per impostarne la posizione nel componibile principale.
@Composable fun CustomView() { var selectedItem by remember { mutableIntStateOf(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 con l'associazione di visualizzazioni
Per incorporare un layout XML, utilizza l'
AndroidViewBinding
API, fornita dalla androidx.compose.ui:ui-viewbinding libreria. Per
farlo, il progetto deve abilitare l'associazione di visualizzazioni.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView negli elenchi Lazy
Se utilizzi un AndroidView in un elenco Lazy (LazyColumn, LazyRow,
Pager, e così via), valuta la possibilità di utilizzare l'overload AndroidView
introdotto nella versione 1.4.0-rc01. Questo overload consente a Compose di riutilizzare l'istanza View sottostante quando la composizione contenente viene riutilizzata, come nel caso degli elenchi Lazy.
Questo overload di AndroidView aggiunge due parametri aggiuntivi:
onReset- Un callback richiamato per segnalare che laViewsta per essere riutilizzata. Questo valore deve essere diverso da null per abilitare il riutilizzo della visualizzazione.onRelease(facoltativo) - Un callback richiamato per segnalare che laViewè uscita dalla composizione e non verrà riutilizzata.
@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() } ) } } }
Frammenti in Compose (passaggio transitorio)
Utilizza il AndroidFragment componibile per aggiungere un Fragment in Compose.
AndroidFragment ha una gestione specifica dei frammenti, ad esempio la rimozione del frammento quando il componibile lascia la composizione.
Per includere un frammento, utilizza il AndroidFragment
componibile. Passa una classe Fragment a AndroidFragment, che aggiunge
un'istanza di quella classe direttamente alla composizione. AndroidFragment fornisce anche un oggetto fragmentState per creare AndroidFragment con un determinato stato, arguments da passare al nuovo frammento e un callback onUpdate che fornisce il frammento dalla composizione. Come molti altri componibili integrati, AndroidFragment accetta un parametro Modifier che puoi utilizzare, ad esempio, per impostarne la posizione nel componibile principale.
Chiama AndroidFragment in Compose come segue:
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
Chiamare il framework Android da Compose
Compose opera all'interno delle classi del framework Android. Ad esempio, è ospitato su classi di visualizzazione Android, come Activity o Fragment, e potrebbe utilizzare classi del framework Android come Context, risorse di sistema, Service o BroadcastReceiver.
Per saperne di più sulle risorse di sistema, consulta Risorse in Compose.
Locali di composizione
CompositionLocal
classi consentono di passare i dati in modo implicito tramite le funzioni componibili. In genere, viene fornito un valore in un determinato nodo dell'albero dell'interfaccia utente. Questo valore può essere utilizzato dai relativi discendenti componibili senza dichiarare CompositionLocal come parametro nella funzione componibile.
CompositionLocal viene utilizzato per propagare i valori per i tipi di framework Android in
Compose, come Context, Configuration o View in cui il codice Compose
è ospitato con i corrispondenti
LocalContext,
LocalConfiguration,
o
LocalView.
Tieni presente che le classi CompositionLocal sono precedute dal prefisso Local per una migliore
rilevabilità con il completamento automatico nell'IDE.
Accedi al valore corrente di un CompositionLocal utilizzando la relativa proprietà current. Ad esempio, il codice riportato di seguito mostra una notifica toast fornendo LocalContext.current nel metodo Toast.makeToast.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Ricevitori di trasmissione
Per mostrare CompositionLocal ed effetti, se è necessario registrare un
BroadcastReceiver da
una funzione componibile, utilizza LocalContext per utilizzare il contesto corrente e
rememberUpdatedState ed DisposableEffect effetti collaterali.
@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 */ }
Altre interazioni
Se non è definita un'utilità per l'interazione di cui hai bisogno, la best practice è seguire le linee guida generali di Compose, i dati scorrono verso il basso, gli eventi scorrono verso l'alto (di cui parleremo più approfonditamente in Pensare in Compose). Ad esempio, questo componibile avvia un'attività diversa:
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) } }