Puoi includere una gerarchia di visualizzazioni 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 della visualizzazione, utilizza il composable AndroidView
. A AndroidView
viene passato un lambda che restituisce un
View
. AndroidView
fornisce anche un callback update
che viene chiamato quando la visualizzazione viene espansa. AndroidView
si ricomponie ogni volta che un valore State
letto all'interno del callback cambia. AndroidView
, come molti altri composabili integrati, accetta un parametro Modifier
che può essere utilizzato, ad esempio, per impostarne la posizione nel composable principale.
@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
con associazione delle visualizzazioni
Per incorporare un layout XML, utilizza l'API
AndroidViewBinding
fornita dalla libreria androidx.compose.ui:ui-viewbinding
. Per farlo, il progetto deve attivare il collegamento delle 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), ti consigliamo di utilizzare l'overload AndroidView
introdotto nella versione 1.4.0-rc01. Questa sovraccarica consente a Compose di riutilizzare
l'istanza View
sottostante quando la composizione contenente viene riutilizzata, come accade per le liste lazy.
Questo sovraccarico di AndroidView
aggiunge altri due parametri:
onReset
: un callback invocato per segnalare cheView
sta per essere riutilizzato. Deve essere diverso da null per consentire il riutilizzo della visualizzazione.onRelease
(facoltativo) - Un callback invocato per segnalare cheView
è uscito dalla composizione e non verrà riutilizzato.
@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() } ) } } }
Frammenti in Compose
Utilizza il composable AndroidViewBinding
per aggiungere un Fragment
in Componi.
AndroidViewBinding
ha un trattamento specifico per i frammenti, ad esempio la rimozione del frammento quando il composable esce dalla composizione.
A tal fine, esegui il pompaggio di un file XML contenente un FragmentContainerView
come contenitore del tuo Fragment
.
Ad esempio, se hai definito my_fragment_layout.xml
, puoi utilizzare un codice come questo sostituendo l'attributo XML android:name
con il nome della classe 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" />
Ingrandisci questo frammento in Componi come segue:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Se devi utilizzare più frammenti nello stesso layout, assicurati di avere definito un ID univoco per ogni FragmentContainerView
.
Chiamare il framework Android da Compose
Compose opera all'interno delle classi del framework Android. Ad esempio, è ospitato su classi View di Android, come Activity
o Fragment
, e potrebbe utilizzare classi del framework Android come Context
, risorse di sistema, Service
o BroadcastReceiver
.
Per scoprire di più sulle risorse di sistema, consulta Risorse in Compose.
Impostazioni internazionali della composizione
Le classi CompositionLocal
consentono di passare i dati in modo implicito tramite funzioni componibili. Generalmente vengono forniti con un valore in un determinato nodo dell'albero dell'interfaccia utente. Questo valore può essere utilizzato dai suoi elementi composibili discendenti senza dichiarare CompositionLocal
come parametro nella funzione componibile.
CompositionLocal
viene utilizzato per propagare i valori per i tipi di framework Android in Compose, ad esempio Context
, Configuration
o View
in cui è ospitato il codice Compose con il corrispondente LocalContext
, LocalConfiguration
o LocalView
.
Tieni presente che i tipi CompositionLocal
sono preceduti da 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 seguente mostra un messaggio di notifica passando
LocalContext.current
al metodo Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Per un esempio più completo, consulta la sezione Case study: BroadcastReceiver alla fine di questo documento.
Altre interazioni
Se non è stata definita un'utilità per l'interazione di cui hai bisogno, la best practice è seguire la linea guida generale di Compose, i dati scorrono verso il basso, gli eventi verso l'alto (discussa più dettagliatamente in Pensare in Compose). Ad esempio, questo composable 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) } }
Case study: broadcast receiver
Per un esempio più realistico delle funzionalità di cui potresti voler eseguire la migrazione o l'implementazione in Compose e per mostrare CompositionLocal
e i effetti collaterali, supponiamo che un BroadcastReceiver
debba essere registrato da una funzione componibile.
La soluzione utilizza LocalContext
per utilizzare il contesto corrente e gli effetti collaterali rememberUpdatedState
e 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 */ }
Passaggi successivi
Ora che conosci le API di interoperabilità quando utilizzi Compose in Visualizzazioni e viceversa, consulta la pagina Altre considerazioni per saperne di più.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Altre considerazioni
- Effetti collaterali in Componi
- Dati con ambito locale con CompositionLocal