Puoi aggiungere un'interfaccia utente basata su Compose a un'app esistente che utilizza un design basato su View.
Per creare una nuova schermata basata interamente su Compose, fai in modo che la tua
attività chiami il metodo setContent()
e passa le funzioni componibili
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 troveresti in un'app solo Compose.
ViewCompositionStrategy
per ComposeView
ViewCompositionStrategy
definisce quando deve essere eliminata la composizione. Il valore predefinito,
ViewCompositionStrategy.Default
,
elimina la composizione quando l'ComposeView
sottostante viene scollegato dalla finestra, a meno che non faccia parte di un contenitore di pooling come un
RecyclerView
. In un'app con una sola attività di sola composizione, questo comportamento predefinito è
quello che vorresti, tuttavia, se aggiungi Compose in modo incrementale nel tuo
codice base, questo comportamento potrebbe causare la perdita di stato in alcuni scenari.
Per modificare ViewCompositionStrategy
, chiama il metodo setViewCompositionStrategy()
e fornisci una strategia diversa.
La tabella seguente riepiloga i diversi scenari in cui puoi utilizzare
ViewCompositionStrategy
:
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 delle visualizzazioni o nel contesto di una schermata mista View/Compose (non in Fragment). |
DisposeOnDetachedFromWindowOrReleasedFromPool (predefinito) |
Analogamente 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, viene eliminato quando il contenitore stesso si stacca dalla finestra o quando l'elemento viene eliminato (ad esempio quando il pool è pieno).Scenario di interoperabilità: * ComposeView se è l'unico elemento nella gerarchia di visualizzazione o nel contesto di una schermata mista View/Compose (non in Fragment).* ComposeView come elemento in un contenitore di pooling come RecyclerView . |
DisposeOnLifecycleDestroyed |
La composizione verrà eliminata quando il Lifecycle fornito viene distrutto.Scenario di interoperabilità * ComposeView nella visualizzazione di un fragment. |
DisposeOnViewTreeLifecycleDestroyed |
La composizione verrà eliminata quando viene distrutto il Lifecycle di proprietà del LifecycleOwner restituito da ViewTreeLifecycleOwner.get della finestra successiva a cui è collegata la visualizzazione.Scenario di interoperabilità: * ComposeView nella visualizzazione di un fragmento.* ComposeView in una visualizzazione in cui il ciclo di vita non è ancora noto. |
ComposeView
in Frammenti
Se vuoi incorporare contenuti dell'interfaccia utente Compose in un fragment o in un layout View 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
layout definita in XML. Poi recupera l'ComposeView
utilizzando l'ID XML, imposta una strategia di composizione più adatta all'host View
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 della visualizzazione 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. Mostra l'output del codice che aggiunge elementi Compose in una
gerarchia dell'interfaccia utente View. Il testo "Hello Android!" viene visualizzato da un widget TextView
. Il testo "Hello Compose!" viene visualizzato da un
elemento di testo di Compose.
Puoi anche includere un ComposeView
direttamente in un fragment se la schermata intera
è creata con Compose, il che ti consente di evitare completamente l'utilizzo di 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 componenti combinabili in Layout Editor
Puoi anche visualizzare l'anteprima dei composable all'interno dell'editor layout per il layout XML
contenente un ComposeView
. In questo modo puoi vedere l'aspetto dei tuoi composable
all'interno di un layout misto di Views e Compose.
Supponiamo di voler visualizzare il seguente elemento componibile nell'editor layout. Nota
che i composable annotati con @Preview
sono buoni candidati per l'anteprima nell'editor del layout.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
Per visualizzare questo componente componibile, utilizza l'attributo tools:composableName
tools e
imposta il relativo valore sul nome completo del componente componibile 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 in Views, scopri come utilizzare Views in Compose.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Altre considerazioni
- Strategia di migrazione {:#migration-strategy}
- Confrontare la composizione e la visualizzazione del rendimento