Вы можете включить иерархию представлений Android в интерфейс Compose. Этот подход особенно полезен, если вы хотите использовать элементы пользовательского интерфейса, которых ещё нет в Compose, например, AdView
. Этот подход также позволяет повторно использовать созданные вами пользовательские представления.
Чтобы включить элемент представления или иерархию, используйте компонуемый объект AndroidView
. AndroidView
передаётся лямбда-выражение, возвращающее View
. AndroidView
также предоставляет функцию обратного вызова update
, которая вызывается при заполнении представления. AndroidView
выполняет повторную компоновку при каждом изменении State
, считанного в функции обратного вызова. AndroidView
, как и многие другие встроенные компонуемые объекты, принимает параметр Modifier
, который можно использовать, например, для задания его положения в родительском компонуемом объекте.
@Composable fun CustomView() { var selectedItem by remember { mutableIntStateOf(0) } // Adds view to Compose AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> // Creates view MyView(context).apply { // Sets up listeners for View -> Compose communication setOnClickListener { selectedItem = 1 } } }, update = { view -> // View's been inflated or state read in this block has been updated // Add logic here if necessary // As selectedItem is read here, AndroidView will recompose // whenever the state changes // Example of Compose -> View communication view.selectedItem = selectedItem } ) } @Composable fun ContentExample() { Column(Modifier.fillMaxSize()) { Text("Look at this CustomView!") CustomView() } }
AndroidView
с привязкой к виду
Для встраивания XML-макета используйте API AndroidViewBinding
, предоставляемый библиотекой androidx.compose.ui:ui-viewbinding
. Для этого в вашем проекте должна быть включена привязка представлений .
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
в ленивых списках
Если вы используете AndroidView
в списке Lazy ( LazyColumn
, LazyRow
, Pager
и т. д.), рассмотрите возможность использования перегрузки AndroidView
, представленной в версии 1.4.0-rc01. Эта перегрузка позволяет Compose повторно использовать базовый экземпляр View
при повторном использовании содержащей его композиции, как в случае с списками Lazy.
Эта перегрузка AndroidView
добавляет 2 дополнительных параметра:
-
onReset
— обратный вызов, сигнализирующий о том, чтоView
будет использовано повторно. Для повторного использования представления это значение должно быть ненулевым. -
onRelease
(необязательно) — обратный вызов, вызываемый для оповещения о том, чтоView
вышло из композиции и не будет использоваться повторно.
@Composable fun AndroidViewInLazyList() { LazyColumn { items(100) { index -> AndroidView( modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI tree factory = { context -> MyView(context) }, update = { view -> view.selectedItem = index }, onReset = { view -> view.clear() } ) } } }
Фрагменты в Compose
Используйте компонуемый объект AndroidViewBinding
для добавления Fragment
в Compose. AndroidViewBinding
имеет специфичную для фрагментов обработку, например, удаляет фрагмент, когда компонуемый объект покидает композицию.
Это можно сделать, развернув XML, содержащий FragmentContainerView
в качестве держателя для вашего Fragment
.
Например, если у вас определен my_fragment_layout.xml
, вы можете использовать такой код, заменив XML-атрибут android:name
именем класса вашего Fragment
:
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_view" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.example.compose.snippets.interop.MyFragment" />
Разместите этот фрагмент в Compose следующим образом:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Если вам нужно использовать несколько фрагментов в одном макете, убедитесь, что вы определили уникальный идентификатор для каждого FragmentContainerView
.
Вызов фреймворка Android из Compose
Compose работает в рамках классов фреймворка Android. Например, он размещается на классах представлений Android, таких как Activity
или Fragment
, и может использовать классы фреймворка Android, такие как Context
, системные ресурсы, Service
или BroadcastReceiver
.
Дополнительную информацию о системных ресурсах см. в разделе Ресурсы в Compose .
Состав Местные жители
Классы CompositionLocal
позволяют неявно передавать данные через компонуемые функции. Обычно им присваивается значение в определённом узле дерева пользовательского интерфейса. Это значение может использоваться компонуемыми потомками без объявления CompositionLocal
в качестве параметра компонуемой функции.
CompositionLocal
используется для распространения значений для типов фреймворка Android в Compose, таких как Context
, Configuration
или View
, в которых размещается код Compose с соответствующими LocalContext
, LocalConfiguration
или LocalView
. Обратите внимание, что классы CompositionLocal
имеют префикс Local
для лучшего поиска с помощью автодополнения в IDE.
Доступ к текущему значению CompositionLocal
осуществляется через его свойство current
. Например, код ниже отображает всплывающее сообщение, передавая LocalContext.current
в метод Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Более полный пример см. в разделе «Пример из практики: BroadcastReceivers» в конце этого документа.
Другие взаимодействия
Если для нужного вам взаимодействия не определена утилита, рекомендуется следовать общему правилу Compose: данные передаются вниз, события — вверх (подробнее обсуждается в разделе «Размышления в Compose »). Например, этот компонуемый объект запускает другую активность:
class OtherInteractionsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // get data from savedInstanceState setContent { MaterialTheme { ExampleComposable(data, onButtonClick = { startActivity(Intent(this, MyActivity::class.java)) }) } } } } @Composable fun ExampleComposable(data: DataExample, onButtonClick: () -> Unit) { Button(onClick = onButtonClick) { Text(data.title) } }
Пример использования: вещательные приемники
Для более реалистичного примера функций, которые вы, возможно, захотите перенести или реализовать в Compose, а также для демонстрации CompositionLocal
и побочных эффектов , предположим, что BroadcastReceiver
необходимо зарегистрировать из компонуемой функции.
Решение использует LocalContext
для использования текущего контекста, а также побочные эффекты rememberUpdatedState
и DisposableEffect
.
@Composable fun SystemBroadcastReceiver( systemAction: String, onSystemEvent: (intent: Intent?) -> Unit ) { // Grab the current context in this part of the UI tree val context = LocalContext.current // Safely use the latest onSystemEvent lambda passed to the function val currentOnSystemEvent by rememberUpdatedState(onSystemEvent) // If either context or systemAction changes, unregister and register again DisposableEffect(context, systemAction) { val intentFilter = IntentFilter(systemAction) val broadcast = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { currentOnSystemEvent(intent) } } context.registerReceiver(broadcast, intentFilter) // When the effect leaves the Composition, remove the callback onDispose { context.unregisterReceiver(broadcast) } } } @Composable fun HomeScreen() { SystemBroadcastReceiver(Intent.ACTION_BATTERY_CHANGED) { batteryStatus -> val isCharging = /* Get from batteryStatus ... */ true /* Do something if the device is charging */ } /* Rest of the HomeScreen */ }
Следующие шаги
Теперь, когда вы знакомы с API-интерфейсами взаимодействия при использовании Compose in Views и наоборот, изучите страницу «Другие соображения» , чтобы узнать больше.
{% дословно %}Рекомендовано для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Другие соображения
- Побочные эффекты в Compose
- Локально доступные данные с CompositionLocal