„Schreiben“ in Ansichten verwenden

Sie können einer vorhandenen App, die ein ansichtenbasiertes Design verwendet, eine Compose-basierte 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 beliebige zusammensetzbare 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 der Code in einer reinen Compose-App.

ViewCompositionStrategy für ComposeView

Mit ViewCompositionStrategy wird festgelegt, wann die Komposition entsorgt werden soll. Bei der Standardeinstellung, ViewCompositionStrategy.Default, wird die Komposition entfernt, wenn sich das zugrunde liegende ComposeView vom Fenster löst, es sei denn, es ist Teil eines Pools-Containers wie RecyclerView. Bei einer App mit nur einer Aktivität und Compose ist dieses Standardverhalten wünschenswert. Wenn Sie Compose jedoch nach und nach in Ihre Codebasis einfügen, kann dieses Verhalten in einigen Fällen zu einem Statusverlust führen.

Rufen Sie zum Ändern der ViewCompositionStrategy die Methode setViewCompositionStrategy() auf und geben Sie eine andere Strategie an.

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 entfernt, wenn das zugrunde liegende ComposeView-Element vom Fenster getrennt wird. Wurde inzwischen durch DisposeOnDetachedFromWindowOrReleasedFromPool ersetzt.

Interop-Szenario:

* ComposeView Ob es sich um das einzige Element in der Ansichtshierarchie handelt oder um einen gemischten Ansichts-/Compose-Bildschirm (nicht im Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (Standard) Ähnlich wie bei DisposeOnDetachedFromWindow, wenn sich die Komposition nicht in einem Pooling-Container wie einem RecyclerView befindet. Wenn sich das Element in einem Pooling-Container befindet, wird es freigegeben, wenn sich der Pooling-Container selbst vom Fenster löst oder das Element verworfen wird (d.h. wenn der Pool voll ist).

Interop-Szenario:

* ComposeView ob es sich um das einzige Element in der Ansichtshierarchie handelt oder um einen gemischten Ansichts-/Compose-Bildschirm (nicht im Fragment).
* ComposeView als Element in einem Pooling-Container wie RecyclerView.
DisposeOnLifecycleDestroyed Die Komposition wird freigegeben, wenn die bereitgestellte Lifecycle zerstört wird.

Interop-Szenario

* ComposeView in der Ansicht eines Fragments.
DisposeOnViewTreeLifecycleDestroyed Die Komposition wird gelöscht, wenn das Lifecycle, das dem LifecycleOwner gehört, das ViewTreeLifecycleOwner.get des nächsten Fensters, an das die Ansicht angehängt ist, zurückgegeben wurde.

Interoperabilitätsszenario:

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

ComposeView in Fragments

Wenn Sie Inhalte der Benutzeroberfläche „Compose“ in ein Fragment oder ein vorhandenes Ansichtslayout einbinden möchten, verwenden Sie ComposeView und rufen Sie die zugehörige 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>

Erhöhen Sie im Kotlin-Quellcode das Layout der in XML definierten Layoutressource. Rufe dann ComposeView mit der XML-ID ab, lege eine Kompositionstrategie fest, die für den Host View am besten geeignet ist, und rufe 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 die Ansichtsbindung auch verwenden, um Verweise auf ComposeView zu erhalten, indem 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, eines über dem anderen

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

Sie können ComposeView auch direkt in ein Fragment einfügen, wenn Ihr Vollbildmodus mit Compose erstellt wurde. So können Sie eine 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 sich im selben Layout mehrere ComposeView-Elemente befinden, 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>

Vorschau von Composeables im Layout-Editor

Für Ihr XML-Layout, das ein ComposeView enthält, können Sie zusammensetzbare Funktionen auch im Layout-Editor als Vorschau ansehen. So können Sie sehen, wie Ihre Compose-Elemente in einem gemischten Layout mit Ansichten und Compose-Elementen aussehen.

Angenommen, Sie möchten das folgende Composeable im Layout-Editor anzeigen. Mit @Preview gekennzeichnete Composeables eignen sich gut für eine Vorschau im Layout-Editor.

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

Wenn Sie dieses Composeable anzeigen möchten, verwenden Sie das Attribut tools:composableName und legen Sie als Wert den voll qualifizierten Namen des Composeables fest, das im Layout als 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>

Im Layout-Editor angezeigte Elemente

Nächste Schritte

Nachdem Sie nun die APIs zur Interoperabilität kennen, mit denen Sie Compose in Ansichten verwenden können, erfahren Sie hier, wie Sie Ansichten in Compose verwenden.