Korzystanie z opcji tworzenia w widokach

Interfejs oparty na widoku możesz dodać do istniejącej aplikacji.

Aby utworzyć nowy ekran oparty całkowicie na Compose, wywołaj w swojej aktywności metodę setContent() i przekaż dowolne funkcje kompozytowe.

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 tylko do tworzenia wiadomości.

ViewCompositionStrategy za ComposeView

ViewCompositionStrategyokreśla, kiedy kompozycja powinna zostać usunięta. Domyślna wartość, ViewCompositionStrategy.Default, usuwa kompozycję, gdy element podstawowy ComposeView odłącza się od okna, chyba że jest częścią kontenera z grupowaniem, takiego jak RecyclerView. W przypadku aplikacji z jedną aktywnością, która korzysta tylko z Compose, takie domyślne zachowanie 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ę.

Tabela poniżej zawiera podsumowanie różnych scenariuszy, w których możesz użyć funkcjiViewCompositionStrategy:

ViewCompositionStrategy Opis i scenariusz interoperacyjności
DisposeOnDetachedFromWindow Skład zostanie usunięty, gdy podstawowy element ComposeView zostanie odłączony od okna. Został zastąpiony przez DisposeOnDetachedFromWindowOrReleasedFromPool.

Scenariusz interoperacyjności:

* ComposeViewczy jest to jedyny element w hierarchii widoku czy w kontekście mieszanego ekranu Widok/Kompozycja (nie w Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (domyślny) Podobnie jak w przypadku DisposeOnDetachedFromWindow, gdy kompozycja nie znajduje się w kontenerze z poolingiem, np. RecyclerView. Jeśli znajduje się w kontenerze zbiorczym, zostanie usunięty, gdy sam kontener zbiorczy zostanie odłączony od okna lub gdy element zostanie odrzucony (czyli gdy pula jest pełna).

Scenariusz interoperacyjności:

* ComposeView niezależnie od tego, czy jest jedynym elementem w hierarchii widoku, czy w kontekście mieszanego ekranu Widok/Kompozycja (nie w Fragment).
* ComposeView jako element w kontenerze zbiorczym, takim jak RecyclerView.
DisposeOnLifecycleDestroyed Kompozycja zostanie usunięta po zniszczeniu podanego elementu Lifecycle.

Scenariusz integracyjny

* ComposeView w widoku fragmentu.
DisposeOnViewTreeLifecycleDestroyed Kompozycja zostanie usunięta, gdy zasób Lifecycle należący do elementu LifecycleOwner zwrócony przez ViewTreeLifecycleOwner.get z następnego okna, do którego jest dołączony widok, zostanie zniszczony.

Scenariusz integracji:

* ComposeView w widoku fragmentu.
* ComposeView w widoku, w którym cykl życia nie jest jeszcze znany.

ComposeView we fragmentach

Jeśli chcesz włączyć treści interfejsu Compose w fragmentie lub istniejącej widocznej części interfejsu, użyj klasy ComposeView i wywołaj jej metodę setContent(). ComposeView to urządzenie z Androidem View.

Element ComposeView możesz umieścić w układzie XML tak, 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 źródłowym kodzie Kotlina napełnij układ z zasobu układu zdefiniowanego w pliku XML. Następnie pobierz ComposeView za pomocą identyfikatora XML, ustaw strategię tworzenia, która najlepiej pasuje do hosta View, i wywołaj setContent(), aby użyć 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ć widoku z powiązaniem, aby uzyskać odwołania do elementu ComposeView, odwołując się do wygenerowanej klasy powiązania w 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
    }
}

2 nieco różniące się elementy tekstowe, jeden nad drugim

Rysunek 1. Pokazuje dane wyjściowe kodu, który dodaje elementy Compose w hierarchii widoku interfejsu. Tekst „Hello Android!” jest wyświetlany przez widget TextView. Tekst „Cześć, Compose” jest wyświetlany przez element tekstowy Compose.

Element ComposeView możesz też umieścić bezpośrednio we fragmencie, jeśli widok pełnego ekranu korzysta z funkcji Compose, co pozwala uniknąć całkowitego użycia 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 wystąpień 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 element savedInstanceState działał prawidłowo.

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 elementów składanych w Edytorze układu

Możesz też wyświetlić podgląd elementów kompozycyjnych w edytorze układów dla układu XML zawierającego ComposeView. Dzięki temu możesz zobaczyć, jak Twoje komponenty wyglądają w układzie mieszanym, łączącym widoki i edytowanie.

Załóżmy, że w Edytorze układów chcesz wyświetlić ten element kompozycyjny. Pamiętaj, że elementy składowe oznaczone etykietą @Preview nadają się do wyświetlania podglądu w Edytorze układu.

@Preview
@Composable
fun GreetingPreview() {
    Greeting(name = "Android")
}

Aby wyświetlić tę kompozycję, użyj atrybutu tools:composableName tools i ustaw jego wartość na pełną nazwę skompilowanej kompozycji, aby wyświetlić jej podgląd 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>

Funkcja kompozycyjna wyświetlana w edytorze układu

Dalsze kroki

Teraz, gdy znasz interfejsy API interoperacyjności, które umożliwiają korzystanie z Compose w widoku, dowiedz się, jak używać widoku w Compose.