Puoi includere una gerarchia di visualizzazione Android in un'interfaccia utente 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 viste personalizzate che potresti aver progettato.
Per includere un elemento di visualizzazione o una gerarchia, utilizza il componibile AndroidView
. AndroidView
viene passata una funzione lambda che restituisce un
View
. AndroidView
fornisce anche un update
callback chiamato quando la visualizzazione viene visualizzata. AndroidView
si ricompone
ogni volta che cambia una lettura di State
all'interno del callback. AndroidView
, come molti
altri composable integrati, accetta un parametro Modifier
che può essere utilizzato, ad esempio, per impostarne la posizione nel composable padre.
@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 visualizzazione
Per incorporare un layout XML, utilizza l'API
AndroidViewBinding
, fornita dalla libreria androidx.compose.ui:ui-viewbinding
. Per
farlo, il progetto deve abilitare il binding delle visualizzazioni.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
in Lazy Lists
Se utilizzi un AndroidView
in un elenco pigro (LazyColumn
, LazyRow
,
Pager
e così via), valuta la possibilità di utilizzare l'overload AndroidView
introdotto nella versione 1.4.0-rc01. Questo sovraccarico consente a Compose di riutilizzare
l'istanza View
sottostante quando la composizione contenente viene riutilizzata così com'è,
come nel caso degli elenchi pigri.
Questo sovraccarico di AndroidView
aggiunge due parametri aggiuntivi:
onReset
: un callback richiamato per segnalare cheView
sta per essere riutilizzato. Questo valore deve essere diverso da null per attivare il riutilizzo della visualizzazione.onRelease
(facoltativo) - Un callback richiamato per segnalare cheView
ha abbandonato la composizione e non verrà più riutilizzato.
@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 componibile AndroidViewBinding
per aggiungere un Fragment
in Compose.
AndroidViewBinding
ha una gestione specifica dei frammenti, ad esempio la rimozione del
frammento quando il componibile esce dalla composizione.
A tal fine, gonfia un file XML contenente un FragmentContainerView
come segnaposto per il 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" />
Gonfia questo frammento in Compose come segue:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Se devi utilizzare più frammenti nello stesso layout, assicurati di aver
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 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.
Composition Locals
Le classi CompositionLocal
consentono di passare i dati in modo implicito tramite le funzioni componibili. Di solito
vengono forniti con un valore in un determinato nodo dell'albero dell'interfaccia utente. Questo valore può
essere utilizzato dai suoi 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, ad esempio Context
, Configuration
o View
in cui è ospitato il codice
Compose con il
LocalContext
,
LocalConfiguration
,
o
LocalView
.
Tieni presente che le classi CompositionLocal
sono precedute da Local
per una migliore
rilevabilità con il completamento automatico nell'IDE.
Accedi al valore corrente di un CompositionLocal
utilizzando la proprietà current
. Ad esempio, il codice riportato di seguito mostra un messaggio di notifica 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") } }
Per un esempio più completo, consulta la sezione Case study: BroadcastReceivers alla fine di questo documento.
Altre interazioni
Se non è definita un'utilità per l'interazione che ti serve, la best practice è seguire le linee guida generali di Compose, i dati scorrono verso il basso, gli eventi verso l'alto (argomento trattato più nel dettaglio in Pensare in Compose). Ad esempio, questo elemento 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) } }
Case study: ricevitori di trasmissioni
Per un esempio più realistico di funzionalità che potresti voler eseguire la migrazione o implementare in Compose e per mostrare gli CompositionLocal
e gli 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 di 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 Views e viceversa, esplora 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 Compose
- Dati con ambito locale con CompositionLocal