Interfejs oparty na Compose możesz dodać do istniejącej aplikacji, która korzysta z projektu opartego na widokach.
Aby utworzyć nowy ekran oparty wyłącznie na Compose, wywołaj w aktywności metodę setContent() i przekaż dowolne funkcje typu „composable”.
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!") }
Ten kod wygląda tak samo jak kod w aplikacji korzystającej tylko z Compose.
ViewCompositionStrategy za ComposeView
ViewCompositionStrategy określa, kiedy kompozycja powinna zostać usunięta. Domyślna strategia ViewCompositionStrategy.Default usuwa kompozycję, gdy powiązany element ComposeView odłącza się od okna, chyba że jest częścią kontenera puli, takiego jak RecyclerView. W aplikacji Compose-only z jedną aktywnością to działanie domyślne jest pożądane, ale jeśli stopniowo dodajesz Compose do bazy kodu, w niektórych przypadkach może to spowodować utratę stanu.
Aby zmienić ViewCompositionStrategy, wywołaj metodę setViewCompositionStrategy() i podaj inną strategię.
W tabeli poniżej znajdziesz podsumowanie różnych scenariuszy, w których możesz używać ViewCompositionStrategy:
ViewCompositionStrategy |
Opis i scenariusz współdziałania |
|---|---|
DisposeOnDetachedFromWindow |
Kompozycja zostanie usunięta, gdy element ComposeView zostanie odłączony od okna. Został zastąpiony przez DisposeOnDetachedFromWindowOrReleasedFromPool.Scenariusz interoperacyjności: * ComposeView, niezależnie od tego, czy jest to jedyny element w hierarchii widoków, czy w kontekście mieszanego ekranu widoku/Compose (nie we fragmencie). |
DisposeOnDetachedFromWindowOrReleasedFromPool (domyślny) |
Podobnie jak w przypadku DisposeOnDetachedFromWindow, gdy kompozycja nie znajduje się w kontenerze puli, takim jak RecyclerView. Jeśli znajduje się w kontenerze puli, zostanie usunięty, gdy sam kontener puli zostanie odłączony od okna lub gdy element zostanie odrzucony (np. gdy pula jest pełna).Scenariusz współdziałania: * ComposeView, czy jest to jedyny element w hierarchii widoków, czy w kontekście mieszanego ekranu widoku/Compose (nie we fragmencie).* ComposeView jako element w kontenerze puli, np. RecyclerView. |
DisposeOnLifecycleDestroyed |
Kompozycja zostanie usunięta, gdy podany element Lifecycle zostanie zniszczony.Scenariusz współdziałania * ComposeView w widoku fragmentu. |
DisposeOnViewTreeLifecycleDestroyed |
Kompozycja zostanie usunięta, gdy Lifecycle należący do LifecycleOwner zwróconego przez ViewTreeLifecycleOwner.get następnego okna, do którego jest dołączony widok, zostanie zniszczony.Scenariusz interoperacyjności: * ComposeView w widoku fragmentu.* ComposeView w widoku, w którym cykl życia nie jest jeszcze znany. |
ComposeView we fragmentach (etap przejściowy)
Jeśli chcesz umieścić treści interfejsu Compose we fragmencie lub istniejącym układzie widoku, użyj ComposeView i wywołaj metodę setContent(). ComposeView to View z Androidem.
Możesz umieścić ComposeView w układzie XML tak samo jak każdy inny element 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>
W kodzie źródłowym Kotlin rozwiń układ z zasobu layoutu zdefiniowanego w pliku XML. Następnie pobierz ComposeView za pomocą identyfikatora XML, ustaw strategię kompozycji, która najlepiej sprawdza się w przypadku hosta View, i wywołaj setContent(), aby użyć funkcji 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 } }
Możesz też użyć powiązania widoku, aby uzyskać odwołania do ComposeView, odwołując się do wygenerowanej klasy powiązania dla pliku układu 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 } }
Rysunek 1. To pokazuje dane wyjściowe kodu, który dodaje elementy Compose w hierarchii interfejsu widoku. Tekst „Hello Android!” jest wyświetlany przez widżet TextView. Tekst „Hello Compose!” jest wyświetlany przez element tekstowy Compose.
Możesz też umieścić ComposeView bezpośrednio we fragmencie, jeśli pełny ekran jest tworzony za pomocą Compose, co pozwala całkowicie uniknąć używania pliku układu 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!") } } } } }
Wiele instancji ComposeView w tym samym układzie
Jeśli w tym samym układzie jest kilka elementów ComposeView, każdy z nich musi mieć unikalny identyfikator, aby usługa savedInstanceState działała.
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 // ... } ) } }
Identyfikatory ComposeView są zdefiniowane w pliku res/values/ids.xml:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
Wyświetlanie podglądu funkcji kompozycyjnych w edytorze układu
Możesz też wyświetlać podgląd funkcji kompozycyjnych w edytorze układu w przypadku układu XML zawierającego element ComposeView. Dzięki temu możesz zobaczyć, jak wyglądają elementy kompozycyjne w układzie mieszanym widoków i Compose.
Załóżmy, że chcesz wyświetlić w edytorze układu tę funkcję kompozycyjną. Pamiętaj, że elementy kompozycyjne oznaczone adnotacją @Preview są dobrymi kandydatami do podglądu w edytorze układu.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
Aby wyświetlić ten element kompozycyjny, użyj atrybutu narzędzi tools:composableName i ustaw jego wartość na pełną nazwę elementu kompozycyjnego, który chcesz wyświetlić w układzie.
<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>
