Использование Compose в представлениях

Вы можете добавить пользовательский интерфейс на основе Compose в существующее приложение, использующее дизайн на основе View.

Чтобы создать новый экран, полностью основанный на Compose, заставьте вашу активность вызвать метод setContent() и передайте любые необходимые вам компонуемые функции.

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

Этот код выглядит так же, как тот, что вы найдете в приложении, поддерживающем только Compose.

ViewCompositionStrategy для ComposeView

ViewCompositionStrategy определяет, когда следует удалять Composition. Значение по умолчанию, ViewCompositionStrategy.Default , удаляет Composition, когда базовый ComposeView отсоединяется от окна, если только он не является частью контейнера пула, такого как RecyclerView . В приложении Compose-only с одним Activity это поведение по умолчанию — то, что вам нужно, однако, если вы постепенно добавляете Compose в свою кодовую базу, это поведение может привести к потере состояния в некоторых сценариях.

Чтобы изменить ViewCompositionStrategy , вызовите метод setViewCompositionStrategy() и укажите другую стратегию.

В таблице ниже обобщены различные сценарии, в которых можно использовать ViewCompositionStrategy :

ViewCompositionStrategy Описание и сценарий взаимодействия
DisposeOnDetachedFromWindow Composition будет удален, когда базовый ComposeView будет отсоединен от окна. С тех пор был заменен на DisposeOnDetachedFromWindowOrReleasedFromPool .

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool ( по умолчанию ) Аналогично DisposeOnDetachedFromWindow , когда Composition не находится в контейнере пула, таком как RecyclerView . Если он находится в контейнере пула, он будет удален, когда либо сам контейнер пула отсоединится от окна, либо когда элемент будет удален (т. е. когда пул заполнен).

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
* ComposeView как элемент в контейнере пула, таком как RecyclerView .
DisposeOnLifecycleDestroyed Композиция будет утилизирована после уничтожения предоставленного Lifecycle .

Сценарий взаимодействия

* ComposeView в представлении фрагмента.
DisposeOnViewTreeLifecycleDestroyed Композиция будет уничтожена, когда Lifecycle , принадлежащий LifecycleOwner , возвращенный ViewTreeLifecycleOwner.get следующего окна, к которому прикреплено представление, будет уничтожен.

Сценарий взаимодействия:

* ComposeView в представлении фрагмента.
* ComposeView в представлении, жизненный цикл которого еще неизвестен.

ComposeView в фрагментах

Если вы хотите включить содержимое Compose UI во фрагмент или существующий макет View, используйте ComposeView и вызовите его метод setContent() . ComposeView — это Android View .

Вы можете поместить ComposeView в свой XML-макет так же, как и любой другой 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>

В исходном коде Kotlin раздуйте макет из ресурса макета , определенного в XML. Затем получите ComposeView , используя XML ID, установите стратегию Composition, которая лучше всего подходит для хостового View , и вызовите setContent() для использования 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
    }
}

В качестве альтернативы вы также можете использовать привязку представления для получения ссылок на ComposeView , ссылаясь на сгенерированный класс привязки для вашего файла макета 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
    }
}

Два немного отличающихся текстовых элемента, один над другим

Рисунок 1. Здесь показан вывод кода, который добавляет элементы Compose в иерархию View UI. Текст "Hello Android!" отображается виджетом TextView . Текст "Hello Compose!" отображается текстовым элементом Compose.

Вы также можете включить ComposeView непосредственно во фрагмент, если ваш полный экран создан с помощью Compose, что позволяет полностью избежать использования 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!")
                }
            }
        }
    }
}

Несколько экземпляров ComposeView в одном макете

Если в одном макете имеется несколько элементов ComposeView , каждый из них должен иметь уникальный идентификатор для работы savedInstanceState .

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

Идентификаторы ComposeView определены в файле res/values/ids.xml :

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

Предварительный просмотр компонуемых объектов в редакторе макетов

Вы также можете предварительно просмотреть компонуемые элементы в редакторе макетов для вашего XML-макета, содержащего ComposeView . Это позволяет вам увидеть, как ваши компонуемые элементы выглядят в смешанном макете Views и Compose.

Допустим, вы хотите отобразить следующий компонуемый объект в редакторе макетов. Обратите внимание, что компонуемые объекты, аннотированные @Preview , являются хорошими кандидатами для предварительного просмотра в редакторе макетов.

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

Чтобы отобразить этот компонуемый элемент, используйте атрибут tools:composableName и задайте для него полное имя компонуемого элемента для предварительного просмотра в макете.

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

Компонуется и отображается в редакторе макетов

Следующие шаги

Теперь, когда вы знакомы с API-интерфейсами взаимодействия для использования Compose в Views, узнайте, как использовать Views в Compose .

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %} ,

Вы можете добавить пользовательский интерфейс на основе Compose в существующее приложение, использующее дизайн на основе View.

Чтобы создать новый экран, полностью основанный на Compose, заставьте вашу активность вызвать метод setContent() и передайте любые необходимые вам компонуемые функции.

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

Этот код выглядит так же, как тот, что вы найдете в приложении, поддерживающем только Compose.

ViewCompositionStrategy для ComposeView

ViewCompositionStrategy определяет, когда следует удалять Composition. Значение по умолчанию, ViewCompositionStrategy.Default , удаляет Composition, когда базовый ComposeView отсоединяется от окна, если только он не является частью контейнера пула, такого как RecyclerView . В приложении Compose-only с одним Activity это поведение по умолчанию — то, что вам нужно, однако, если вы постепенно добавляете Compose в свою кодовую базу, это поведение может привести к потере состояния в некоторых сценариях.

Чтобы изменить ViewCompositionStrategy , вызовите метод setViewCompositionStrategy() и укажите другую стратегию.

В таблице ниже обобщены различные сценарии, в которых можно использовать ViewCompositionStrategy :

ViewCompositionStrategy Описание и сценарий взаимодействия
DisposeOnDetachedFromWindow Composition будет удален, когда базовый ComposeView будет отсоединен от окна. С тех пор был заменен на DisposeOnDetachedFromWindowOrReleasedFromPool .

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool ( по умолчанию ) Аналогично DisposeOnDetachedFromWindow , когда Composition не находится в контейнере пула, таком как RecyclerView . Если он находится в контейнере пула, он будет удален, когда либо сам контейнер пула отсоединится от окна, либо когда элемент будет удален (т. е. когда пул заполнен).

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
* ComposeView как элемент в контейнере пула, таком как RecyclerView .
DisposeOnLifecycleDestroyed Композиция будет утилизирована после уничтожения предоставленного Lifecycle .

Сценарий взаимодействия

* ComposeView в представлении фрагмента.
DisposeOnViewTreeLifecycleDestroyed Композиция будет уничтожена, когда Lifecycle , принадлежащий LifecycleOwner , возвращенный ViewTreeLifecycleOwner.get следующего окна, к которому прикреплено представление, будет уничтожен.

Сценарий взаимодействия:

* ComposeView в представлении фрагмента.
* ComposeView в представлении, жизненный цикл которого еще неизвестен.

ComposeView в фрагментах

Если вы хотите включить содержимое Compose UI во фрагмент или существующий макет View, используйте ComposeView и вызовите его метод setContent() . ComposeView — это Android View .

Вы можете поместить ComposeView в свой XML-макет так же, как и любой другой 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>

В исходном коде Kotlin раздуйте макет из ресурса макета , определенного в XML. Затем получите ComposeView , используя XML ID, установите стратегию Composition, которая лучше всего подходит для хостового View , и вызовите setContent() для использования 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
    }
}

В качестве альтернативы вы также можете использовать привязку представления для получения ссылок на ComposeView , ссылаясь на сгенерированный класс привязки для вашего файла макета 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
    }
}

Два немного отличающихся текстовых элемента, один над другим

Рисунок 1. Здесь показан вывод кода, который добавляет элементы Compose в иерархию View UI. Текст "Hello Android!" отображается виджетом TextView . Текст "Hello Compose!" отображается текстовым элементом Compose.

Вы также можете включить ComposeView непосредственно во фрагмент, если ваш полный экран создан с помощью Compose, что позволяет полностью избежать использования 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!")
                }
            }
        }
    }
}

Несколько экземпляров ComposeView в одном макете

Если в одном макете имеется несколько элементов ComposeView , каждый из них должен иметь уникальный идентификатор для работы savedInstanceState .

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

Идентификаторы ComposeView определены в файле res/values/ids.xml :

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

Предварительный просмотр компонуемых объектов в редакторе макетов

Вы также можете предварительно просмотреть компонуемые элементы в редакторе макетов для вашего XML-макета, содержащего ComposeView . Это позволяет вам увидеть, как ваши компонуемые элементы выглядят в смешанном макете Views и Compose.

Допустим, вы хотите отобразить следующий компонуемый объект в редакторе макетов. Обратите внимание, что компонуемые объекты, аннотированные @Preview , являются хорошими кандидатами для предварительного просмотра в редакторе макетов.

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

Чтобы отобразить этот компонуемый элемент, используйте атрибут tools:composableName и задайте для него полное имя компонуемого элемента для предварительного просмотра в макете.

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

Компонуется и отображается в редакторе макетов

Следующие шаги

Теперь, когда вы знакомы с API-интерфейсами взаимодействия для использования Compose в Views, узнайте, как использовать Views в Compose .

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %} ,

Вы можете добавить пользовательский интерфейс на основе Compose в существующее приложение, использующее дизайн на основе View.

Чтобы создать новый экран, полностью основанный на Compose, заставьте вашу активность вызвать метод setContent() и передайте любые необходимые вам компонуемые функции.

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

Этот код выглядит так же, как тот, что вы найдете в приложении, поддерживающем только Compose.

ViewCompositionStrategy для ComposeView

ViewCompositionStrategy определяет, когда следует удалять Composition. Значение по умолчанию, ViewCompositionStrategy.Default , удаляет Composition, когда базовый ComposeView отсоединяется от окна, если только он не является частью контейнера пула, такого как RecyclerView . В приложении Compose-only с одним Activity это поведение по умолчанию — то, что вам нужно, однако, если вы постепенно добавляете Compose в свою кодовую базу, это поведение может привести к потере состояния в некоторых сценариях.

Чтобы изменить ViewCompositionStrategy , вызовите метод setViewCompositionStrategy() и укажите другую стратегию.

В таблице ниже обобщены различные сценарии, в которых можно использовать ViewCompositionStrategy :

ViewCompositionStrategy Описание и сценарий взаимодействия
DisposeOnDetachedFromWindow Composition будет удален, когда базовый ComposeView будет отсоединен от окна. С тех пор был заменен на DisposeOnDetachedFromWindowOrReleasedFromPool .

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool ( по умолчанию ) Аналогично DisposeOnDetachedFromWindow , когда Composition не находится в контейнере пула, таком как RecyclerView . Если он находится в контейнере пула, он будет удален, когда либо сам контейнер пула отсоединится от окна, либо когда элемент будет удален (т. е. когда пул заполнен).

Сценарий взаимодействия:

* ComposeView независимо от того, является ли он единственным элементом в иерархии View или находится в контексте смешанного экрана View/Compose (не в Fragment).
* ComposeView как элемент в контейнере пула, таком как RecyclerView .
DisposeOnLifecycleDestroyed Композиция будет утилизирована после уничтожения предоставленного Lifecycle .

Сценарий взаимодействия

* ComposeView в представлении фрагмента.
DisposeOnViewTreeLifecycleDestroyed Композиция будет уничтожена, когда Lifecycle , принадлежащий LifecycleOwner , возвращенный ViewTreeLifecycleOwner.get следующего окна, к которому прикреплено представление, будет уничтожен.

Сценарий взаимодействия:

* ComposeView в представлении фрагмента.
* ComposeView в представлении, жизненный цикл которого еще неизвестен.

ComposeView в фрагментах

Если вы хотите включить содержимое Compose UI во фрагмент или существующий макет View, используйте ComposeView и вызовите его метод setContent() . ComposeView — это Android View .

Вы можете поместить ComposeView в свой XML-макет так же, как и любой другой 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>

В исходном коде Kotlin раздуйте макет из ресурса макета , определенного в XML. Затем получите ComposeView , используя XML ID, установите стратегию Composition, которая лучше всего подходит для хостового View , и вызовите setContent() для использования 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
    }
}

В качестве альтернативы вы также можете использовать привязку представления для получения ссылок на ComposeView , ссылаясь на сгенерированный класс привязки для вашего файла макета 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
    }
}

Два немного отличающихся текстовых элемента, один над другим

Рисунок 1. Здесь показан вывод кода, который добавляет элементы Compose в иерархию View UI. Текст "Hello Android!" отображается виджетом TextView . Текст "Hello Compose!" отображается текстовым элементом Compose.

Вы также можете включить ComposeView непосредственно во фрагмент, если ваш полный экран создан с помощью Compose, что позволяет полностью избежать использования 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!")
                }
            }
        }
    }
}

Несколько экземпляров ComposeView в одном макете

Если в одном макете имеется несколько элементов ComposeView , каждый из них должен иметь уникальный идентификатор для работы savedInstanceState .

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

Идентификаторы ComposeView определены в файле res/values/ids.xml :

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

Предварительный просмотр компонуемых объектов в редакторе макетов

Вы также можете предварительно просмотреть компонуемые элементы в редакторе макетов для вашего XML-макета, содержащего ComposeView . Это позволяет вам увидеть, как ваши компонуемые элементы выглядят в смешанном макете Views и Compose.

Допустим, вы хотите отобразить следующий компонуемый объект в редакторе макетов. Обратите внимание, что компонуемые объекты, аннотированные @Preview , являются хорошими кандидатами для предварительного просмотра в редакторе макетов.

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

Чтобы отобразить этот компонуемый элемент, используйте атрибут tools:composableName и задайте для него полное имя компонуемого элемента для предварительного просмотра в макете.

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

Компонуется и отображается в редакторе макетов

Следующие шаги

Теперь, когда вы знакомы с API-интерфейсами взаимодействия для использования Compose в Views, узнайте, как использовать Views в Compose .

{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}