„Schreiben“ in Ansichten verwenden

Sie können einer vorhandenen App, die auf einem View-basierten Design basiert, eine auf Compose basierende Benutzeroberfläche hinzufügen.

Wenn Sie einen neuen, vollständig auf Compose basierenden Bildschirm erstellen möchten, rufen Sie in Ihrer Aktivität die Methode setContent() auf und übergeben Sie alle gewünschten zusammensetzbaren Funktionen.

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!")
}

Dieser Code sieht genauso aus wie in einer reinen Compose-App.

ViewCompositionStrategy für ComposeView

ViewCompositionStrategy definiert, wann die Komposition verworfen werden soll. Standardmäßig wird die Komposition mit ViewCompositionStrategy.Default verworfen, wenn das zugrunde liegende ComposeView vom Fenster getrennt wird, es sei denn, es ist Teil eines Pooling-Containers wie RecyclerView. In einer reinen Compose-App mit nur einer Activity ist dieses Standardverhalten erwünscht. Wenn Sie Compose jedoch inkrementell in Ihre Codebasis einfügen, kann es in einigen Szenarien zu einem Verlust des Status kommen.

Rufen Sie die Methode setViewCompositionStrategy() auf und geben Sie eine andere Strategie an, um die ViewCompositionStrategy zu ändern.

In der folgenden Tabelle sind die verschiedenen Szenarien zusammengefasst, in denen Sie ViewCompositionStrategy verwenden können:

ViewCompositionStrategy Beschreibung und Interoperabilitätsszenario
DisposeOnDetachedFromWindow Die Komposition wird verworfen, wenn das zugrunde liegende ComposeView vom Fenster getrennt wird. Wurde inzwischen durch DisposeOnDetachedFromWindowOrReleasedFromPool ersetzt.

Interop-Szenario:

* ComposeView, ob es das einzige Element in der View-Hierarchie ist oder im Kontext eines gemischten View-/Compose-Bildschirms (nicht in einem Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (Standard) Ähnlich wie bei DisposeOnDetachedFromWindow, wenn sich die Komposition nicht in einem Pooling-Container wie einem RecyclerView befindet. Wenn es sich in einem Pooling-Container befindet, wird es verworfen, wenn sich entweder der Pooling-Container selbst vom Fenster löst oder wenn das Element verworfen wird (d.h. wenn der Pool voll ist).

Interop-Szenario:

* ComposeView, ob es sich um das einzige Element in der View-Hierarchie handelt oder im Kontext eines gemischten View-/Compose-Bildschirms (nicht in einem Fragment).
* ComposeView als Element in einem Pooling-Container wie RecyclerView.
DisposeOnLifecycleDestroyed Die Komposition wird verworfen, wenn das bereitgestellte Lifecycle zerstört wird.

Interop-Szenario

* ComposeView in der Ansicht eines Fragments.
DisposeOnViewTreeLifecycleDestroyed Die Komposition wird verworfen, wenn die Lifecycle, die der von ViewTreeLifecycleOwner.get des nächsten Fensters, an das die Ansicht angehängt ist, zurückgegebenen LifecycleOwner gehört, zerstört wird.

Interop-Szenario:

* ComposeView in der Ansicht eines Fragments.
* ComposeView in einer Ansicht, in der der Lebenszyklus noch nicht bekannt ist.

ComposeView in Fragmenten

Wenn Sie Compose-UI-Inhalte in ein Fragment oder ein vorhandenes View-Layout einfügen möchten, verwenden Sie ComposeView und rufen Sie die Methode setContent() auf. ComposeView ist ein Android-View.

Sie können das ComposeView wie jedes andere View in Ihr XML-Layout einfügen:

<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>

Im Kotlin-Quellcode wird das Layout aus der in XML definierten Layout-Ressource aufgebläht. Rufen Sie dann die ComposeView mit der XML-ID ab, legen Sie eine Kompositionsstrategie fest, die am besten für den Host View geeignet ist, und rufen Sie setContent() auf, um Compose zu verwenden.

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
    }
}

Alternativ können Sie auch die Ansichtsbindung verwenden, um Referenzen auf die ComposeView zu erhalten. Dazu müssen Sie auf die generierte Bindungsklasse für Ihre XML-Layoutdatei verweisen:

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
    }
}

Zwei leicht unterschiedliche Textelemente übereinander

Abbildung 1: Hier sehen Sie die Ausgabe des Codes, mit dem Compose-Elemente in eine View-UI-Hierarchie eingefügt werden. Der Text „Hello Android!“ wird von einem TextView-Widget angezeigt. Der Text „Hello Compose!“ wird von einem Compose-Textelement angezeigt.

Sie können auch ein ComposeView direkt in ein Fragment einfügen, wenn Ihr Vollbild mit Compose erstellt wurde. So können Sie die Verwendung einer XML-Layoutdatei vollständig vermeiden.

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!")
                }
            }
        }
    }
}

Mehrere ComposeView-Instanzen im selben Layout

Wenn im selben Layout mehrere ComposeView-Elemente vorhanden sind, muss jedes eine eindeutige ID haben, damit savedInstanceState funktioniert.

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
                // ...
            }
        )
    }
}

Die ComposeView-IDs sind in der Datei res/values/ids.xml definiert:

<resources>
  <item name="compose_view_x" type="id" />
  <item name="compose_view_y" type="id" />
</resources>

Composables im Layout Editor in der Vorschau ansehen

Sie können sich auch eine Vorschau von Composables im Layout-Editor für Ihr XML-Layout mit einem ComposeView ansehen. So können Sie sehen, wie Ihre Composables in einem Layout mit gemischten Views und Compose-Elementen aussehen.

Angenommen, Sie möchten das folgende Composable im Layout-Editor anzeigen. Mit @Preview annotierte Composables eignen sich gut für die Vorschau im Layout-Editor.

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

Um diese Composable anzuzeigen, verwenden Sie das Attribut tools:composableName und legen Sie seinen Wert auf den vollständig qualifizierten Namen der Composable fest, die im Layout in der Vorschau angezeigt werden soll.

<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>

Composable im Layout-Editor angezeigt

Nächste Schritte

Nachdem Sie nun die Interoperabilitäts-APIs kennen, mit denen Sie Compose in Views verwenden können, erfahren Sie, wie Sie Views in Compose verwenden.