Вы можете включить иерархию представлений 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