Puoi aggiungere un'interfaccia utente basata su Compose a un'app esistente che utilizza un design basato su View.
Per creare una nuova schermata interamente basata su Compose, fai in modo che la tua attività chiami il metodo setContent()
e trasmetta le funzioni composable che preferisci.
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
Questo codice è simile a quello che trovi in un'app solo di composizione.
ViewCompositionStrategy
per ComposeView
ViewCompositionStrategy
definisce quando eliminare la composizione. Il valore predefinito,
ViewCompositionStrategy.Default
,
rimuove la composizione quando la
ComposeView
sottostante si scollegano dalla finestra, a meno che non facciano parte di un contenitore per il pooling come un
RecyclerView
. In un'app con una sola attività e solo Compose, questo comportamento predefinito è quello che ti aspetteresti, tuttavia, se aggiungi Compose in modo incrementale al tuo codebase, questo comportamento potrebbe causare la perdita dello stato in alcuni scenari.
Per modificare ViewCompositionStrategy
, chiama il metodo setViewCompositionStrategy()
e fornisci una strategia diversa.
La tabella seguente riassume i diversi scenari che puoi utilizzare
ViewCompositionStrategy
in:
ViewCompositionStrategy |
Descrizione e scenario di interoperabilità |
---|---|
DisposeOnDetachedFromWindow |
La composizione verrà eliminata quando il ComposeView sottostante viene scollegato dalla finestra. È stato sostituito da DisposeOnDetachedFromWindowOrReleasedFromPool .Scenario di interoperabilità: * ComposeView se è l'unico elemento nella gerarchia di View o nel contesto di una schermata di visualizzazione/composizione mista (non in Fragment). |
DisposeOnDetachedFromWindowOrReleasedFromPool (valore predefinito) |
Simile a DisposeOnDetachedFromWindow , quando la composizione non si trova in un contenitore di pooling, ad esempio un RecyclerView . Se si trova in un contenitore di pooling, verrà eliminato quando il contenitore di pooling stesso si scollegherà dalla finestra o quando l'elemento verrà eliminato (ad esempio quando il pool è pieno).Scenario di interoperabilità: * ComposeView se è l'unico elemento nella gerarchia di View o nel contesto di una schermata View/Compose mista (non in Fragment).* ComposeView come elemento in un contenitore di pooling come RecyclerView . |
DisposeOnLifecycleDestroyed |
La composizione verrà eliminata quando l'oggetto Lifecycle fornito verrà distrutto.Scenario di interoperabilità * ComposeView nella visualizzazione di un frammento. |
DisposeOnViewTreeLifecycleDestroyed |
La composizione verrà eliminata quando l'Lifecycle di proprietà dell'LifecycleOwner restituito da ViewTreeLifecycleOwner.get della finestra successiva a cui è associata la visualizzazione viene distrutta.Scenario di interoperabilità: * ComposeView nella visualizzazione di un frammento.* ComposeView in una visualizzazione in cui il ciclo di vita non è ancora noto. |
ComposeView
in Frammenti
Se vuoi incorporare i contenuti dell'interfaccia utente di Compose in un frammento o in un layout della vista esistente, utilizza ComposeView
e chiama il relativo metodo setContent()
. ComposeView
è un View
Android.
Puoi inserire ComposeView
nel layout XML come qualsiasi altro View
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Nel codice sorgente Kotlin, gonfia il layout dalla risorsa
di layout definita in XML. Quindi, recupera il valore ComposeView
utilizzando l'ID XML, imposta una strategia di composizione più adatta all'View
host e chiama setContent()
per utilizzare Compose.
class ExampleFragmentXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_example, container, false) val composeView = view.findViewById<ComposeView>(R.id.compose_view) composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } }
In alternativa, puoi anche utilizzare il binding delle visualizzazioni per ottenere riferimenti a ComposeView
facendo riferimento alla classe di binding generata per il file di layout XML:
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
Figura 1. Viene mostrato l'output del codice che aggiunge elementi di composizione in una gerarchia dell'interfaccia utente di View. Il testo "Hello Android!" viene visualizzato da un
TextView
widget. Il testo "Un saluto da Scrivi" viene visualizzato da un elemento di testo di Scrivi.
Puoi anche includere un ComposeView
direttamente in un frammento se la schermata completa è stata creata con Compose, il che ti consente di evitare di utilizzare completamente un file di layout XML.
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
Più istanze di ComposeView
nello stesso layout
Se nello stesso layout sono presenti più elementi ComposeView
, ognuno deve avere un ID univoco per il funzionamento di savedInstanceState
.
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
Gli ID ComposeView
sono definiti nel file res/values/ids.xml
:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
Visualizzare l'anteprima dei composabili in Layout Editor
Puoi anche visualizzare l'anteprima dei composabili nell'editor di layout per il layout XML contenente un ComposeView
. In questo modo puoi vedere l'aspetto dei tuoi composabili
in un layout misto di Visualizzazioni e Compose.
Supponiamo che tu voglia visualizzare il seguente composable nell'editor di layout. Tieni presente
che i composabili annotati con @Preview
sono ottimi candidati per l'anteprima nell'Editor di layout.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
Per visualizzare questo composable, utilizza l'attributo tools:composableName
tools e imposta il relativo valore sul nome completo del composable da visualizzare in anteprima nel layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.compose.ui.platform.ComposeView android:id="@+id/my_compose_view" tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview" android:layout_height="match_parent" android:layout_width="match_parent"/> </LinearLayout>
Passaggi successivi
Ora che conosci le API di interoperabilità per utilizzare Compose nelle visualizzazioni, scopri come utilizzare le visualizzazioni in Compose.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Altre considerazioni
- Strategia di migrazione {:#migration-strategy}
- Confrontare il rendimento di Scrittura e Visualizza