„Schreiben“ in Ansichten verwenden

Sie können eine auf Schreiben basierende UI in eine vorhandene Anwendung einfügen, die ein ansichtsbasiertes Design verwendet.

Wenn Sie einen neuen Bildschirm erstellen möchten, der vollständig auf Text basiert, rufen Sie 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 eine Anwendung, die nur das Schreiben erstellt.

ViewCompositionStrategy für ComposeView

ViewCompositionStrategy definiert, wann die Komposition verworfen werden soll. Durch den Standardwert ViewCompositionStrategy.Default wird die Zusammensetzung entfernt, wenn sich der zugrunde liegende ComposeView vom Fenster trennt, es sei denn, er ist Teil eines Pooling-Containers wie RecyclerView. Dieses Standardverhalten in einer reinen Erstellungsanwendung mit einer Aktivität ist das gewünschte Verhalten. Wenn Sie jedoch Compose inkrementell zu Ihrer Codebasis hinzufügen, kann dieses Verhalten in einigen Szenarien zu Statusverlusten führen.

Wenn Sie ViewCompositionStrategy ändern möchten, rufen Sie die Methode setViewCompositionStrategy() auf und geben Sie eine andere Strategie an.

In der folgenden Tabelle sind die verschiedenen Szenarien zusammengefasst, in denen ViewCompositionStrategy verwendet werden kann:

ViewCompositionStrategy Beschreibung und Interop-Szenario
DisposeOnDetachedFromWindow Die Komposition wird entfernt, wenn die zugrunde liegende ComposeView vom Fenster getrennt wird. wurde inzwischen durch DisposeOnDetachedFromWindowOrReleasedFromPool ersetzt.

Interoperabilitätsszenario:

* ComposeView – egal, ob es sich um das einzige Element in der Ansichtshierarchie oder im Kontext eines gemischten Ansichts-/Schreibbildschirms handelt (nicht in Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (Standard) Ähnlich wie bei DisposeOnDetachedFromWindow, wenn sich die Zusammensetzung nicht in einem Pooling-Container wie z. B. RecyclerView befindet. Befindet sich der Container in einem Pooling-Container, wird er entsorgt, wenn er sich entweder vom Fenster löst oder wenn das Element verworfen wird, d.h. wenn der Pool voll ist.

Interop-Szenario:

* ComposeView Gibt an, ob es sich um das einzige Element in der Ansichtshierarchie oder im Kontext eines gemischten Ansichts-/Schreibbildschirms (nicht im Fragment) handelt.
* ComposeView als Element in einem Pooling-Container wie RecyclerView.
DisposeOnLifecycleDestroyed Die Komposition wird verworfen, wenn das angegebene Lifecycle gelöscht wird.

Interop-Szenario

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

Interop-Szenario:

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

ComposeView in Fragmenten

Wenn Sie Inhalte der Compose-UI 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-Gerät (View).

Du kannst ComposeView wie jede andere View in dein 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>

Infließen Sie im Kotlin-Quellcode das Layout mit der in XML definierten Layoutressource. Rufen Sie dann die ComposeView mithilfe der XML-ID ab, legen Sie eine Zusammensetzungsstrategie fest, die am besten für den Host View geeignet ist, und rufen Sie setContent() auf, um die Funktion „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 Verweise auf ComposeView zu erhalten. Verweisen Sie hierzu auf die generierte Bindungsklasse für Ihre XML-Layoutdatei:

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, eins übereinander

Abbildung 1: Hier sehen Sie die Ausgabe des Codes, durch den Compose-Elemente in einer Ansichts-UI-Hierarchie hinzugefügt werden. Der Text „Hello Android!“ wird in einem TextView-Widget angezeigt. Der Text „Hello Compose!“ wird in einem Textelement angezeigt.

Sie können ein ComposeView auch direkt in ein Fragment einfügen, wenn Ihr Vollbild mit der Funktion „Compose“ erstellt wurde. So müssen Sie keine XML-Layoutdatei mehr verwenden.

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 es mehrere ComposeView-Elemente im selben Layout gibt, muss jedes Element 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 zusammensetzbarer Funktionen im Layout-Editor ansehen

Im Layout-Editor können Sie zusammensetzbare Funktionen für Ihr XML-Layout, das ein ComposeView enthält, auch als Vorschau ansehen. So können Sie sehen, wie Ihre zusammensetzbaren Funktionen in einem gemischten Layout mit Ansichten und Erstellungselementen dargestellt werden.

Angenommen, Sie möchten die folgende zusammensetzbare Funktion im Layout-Editor anzeigen. Mit @Preview gekennzeichnete zusammensetzbare Funktionen eignen sich gut für die Vorschau im Layout-Editor.

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

Verwenden Sie zum Anzeigen dieser zusammensetzbaren Funktion das Attribut tools:composableName und legen Sie als Wert den voll qualifizierten Namen der zusammensetzbaren Funktion fest, für die eine Vorschau im Layout 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>

Zusammensetzbare Funktion wird im Layout-Editor angezeigt

Nächste Schritte

Sie kennen nun die Interoperabilitäts-APIs für die Verwendung von „Compose“ in Ansichten. Im nächsten Abschnitt erfahren Sie, wie Sie Views in Compose verwenden.