Найти тему

Дружим XML и Jetpack Compose

Оглавление

Jetpack Compose — современный набор инструментов для создания UI с рядом преимуществ. Особенно отметим возможность перехода на один язык программирования для всего приложения, что позволяет избавиться от XML-файлов.

Обеспечиваемая поддержка совместимости позволяет Compose и View сосуществовать в базе кода. Благодаря этому вы можете добавлять новые функциональности с помощью Compose или переносить в него небольшие имеющиеся компоненты.

Compose в View

Добавляем ComposeView в макет XML:

<androidx.compose.ui.platform.ComposeView
android:id="@+id/composeView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

Получаем доступ в Compose из макета XML:

binding.composeView.apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
Text(text = "Hello in Compose World!")
}
}
}

Или Реализуем ComposeView как представление виджета и получаем доступ в Compose:

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
Text(text = "Hello in Compose World!")
}
}
}

View в Compose

Создаем пользовательское представление в factory, а также настраиваем слушателей события клика и обратные вызовы для взаимодействия View -> Compose. Затем при обновлении настраиваем взаимодействие для Compose -> View:

@Composable
fun XMLCounter() {
var resultState by remember { mutableStateOf(0) }
AndroidView(
factory = { context ->
CounterView(context).apply {
// Пример взаимодействия View -> Compose
resultCallback = {
resultState = it
}
}
},
update = { counterView ->
// Пример взаимодействия Compose -> View
counterView.binding.result.text = resultState.toString()
}
)

Расширяем ViewBinding в Compose и получаем доступ к классу Binding:

@Composable
fun XMLCounterBinding() {
AndroidViewBinding(ComponentCounterBinding::inflate) {
down.setOnClickListener { /*...*/ }
up.setOnClickListener { /*...*/ }
}
}

Fragment в Compose

Добавляем FragmentContainerView в макет XML:

<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:name="com.artf.composeinview.ui.main.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />

Получаем доступ к Fragment из Compose:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
AndroidViewBinding(ActivityMainBinding::inflate) {
val fragment = container.getFragment<MainFragment>()
//...
}
}
}
}