É possível incluir uma hierarquia de visualização do Android em uma IU do Compose. Essa abordagem vai ser
útil principalmente se você quiser usar elementos da interface que ainda não estão disponíveis no
Compose, como
AdView
.
Essa abordagem também permite reutilizar visualizações personalizadas que você pode ter criado.
Para incluir um elemento ou uma hierarquia de visualização, use o elemento combinável
AndroidView
. AndroidView
recebe uma lambda que retorna uma
View
. AndroidView
também fornece um callback update
que é chamado quando a visualização é inflada. A AndroidView
faz a recomposição
sempre que um State
lido dentro do callback muda. A AndroidView
, assim como vários
outros elementos combináveis integrados, aceita um parâmetro Modifier
que pode ser usado, por
exemplo, para definir a posição dela no elemento combinável pai.
@Composable fun CustomView() { var selectedItem by remember { mutableStateOf(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
com vinculação de visualizações
Para incorporar um layout XML, use a API
AndroidViewBinding
,
que é fornecida pela biblioteca androidx.compose.ui:ui-viewbinding
. Para
isso, seu projeto precisa ativar a vinculação de visualizações.
@Composable fun AndroidViewBindingExample() { AndroidViewBinding(ExampleLayoutBinding::inflate) { exampleView.setBackgroundColor(Color.GRAY) } }
AndroidView
em listas lentas
Se você estiver usando um AndroidView
em uma lista Lazy (LazyColumn
, LazyRow
,
Pager
etc.), use a sobrecarga AndroidView
introduzida na versão 1.4.0-rc01. Essa sobrecarga permite que o Compose reutilize
a instância View
subjacente quando a composição que contém é reutilizada, como
é o caso das listas Lazy.
Essa sobrecarga de AndroidView
adiciona dois parâmetros:
onReset
: um callback invocado para sinalizar que oView
está prestes a ser reutilizado. Ele precisa ser diferente de "null" para permitir o reuso da visualização.onRelease
(opcional): um callback invocado para sinalizar que oView
saiu da composição e não será reutilizado.
@OptIn(ExperimentalComposeUiApi::class) @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() } ) } } }
Fragmentos no Compose
Use o elemento combinável AndroidViewBinding
para adicionar um Fragment
no Compose.
O AndroidViewBinding
inclui processamentos específicos de fragmentos, como remover o
fragmento quando o elemento combinável sai da composição.
Para isso, infle o XML contendo uma FragmentContainerView
como detentora do Fragment
.
Por exemplo, se você tiver o my_fragment_layout.xml
definido, poderá usar
um código como este ao substituir o atributo android:name
do XML pelo
nome da classe de 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" />
Infle esse fragmento no Compose desta maneira:
@Composable fun FragmentInComposeExample() { AndroidViewBinding(MyFragmentLayoutBinding::inflate) { val myFragment = fragmentContainerView.getFragment<MyFragment>() // ... } }
Se você precisa usar vários fragmentos no mesmo layout, defina
um ID exclusivo para cada FragmentContainerView
.
Como chamar o framework do Android no Compose
O Compose opera dentro das classes do framework do Android. Por exemplo, ele é hospedado
em classes de visualização do Android, como Activity
ou Fragment
, e pode precisar
usar classes do framework do Android, como Context
, recursos do sistema,
Service
ou BroadcastReceiver
.
Para saber mais sobre recursos do sistema, consulte Recursos no Compose.
Classes Composition Locals
As classes CompositionLocal
permitem transmitir dados implicitamente usando funções combináveis. Em geral, elas
recebem um valor em determinado nó da árvore da interface. Esse valor pode
ser usado pelos descendentes combináveis sem declarar o CompositionLocal
como um parâmetro na função combinável.
O CompositionLocal
é usado na propagação de valores para tipos de framework do Android no
Compose (como Context
, Configuration
ou View
) em que o código do Compose
é hospedado com o LocalContext
,
LocalConfiguration
ou
LocalView
correspondente.
As classes CompositionLocal
têm o prefixo Local
para melhor
detecção do dispositivo com o preenchimento automático no ambiente de desenvolvimento integrado.
Acesse o valor atual de um CompositionLocal
usando a propriedade
current
. Por exemplo, o código abaixo mostra uma mensagem de aviso usando
LocalContext.current
no método Toast.makeToast
.
@Composable fun ToastGreetingButton(greeting: String) { val context = LocalContext.current Button(onClick = { Toast.makeText(context, greeting, Toast.LENGTH_SHORT).show() }) { Text("Greet") } }
Para ver um exemplo mais completo, confira a seção Estudo de caso: BroadcastReceivers no fim deste documento.
Outras interações
Caso não haja um utilitário definido para a interação necessária, a prática recomendada é seguir as diretrizes gerais do Compose (o fluxo de dados desce, os eventos sobem), discutidas com mais detalhes em Como trabalhar com o Compose. Por exemplo, este elemento combinável inicia uma atividade diferente:
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) } }
Estudo de caso: broadcast receivers
Para ver um exemplo mais realista dos recursos que você quer migrar ou implementar
no Compose e para demonstrar o CompositionLocal
e os efeitos
colaterais, digamos que um
BroadcastReceiver
precise ser registrado usando
uma função combinável.
A solução utiliza LocalContext
para usar o contexto atual e
os efeitos colaterais de rememberUpdatedState
e 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 */ }
Próximas etapas
Agora que você conhece as APIs de interoperabilidade ao usar o Compose nas visualizações e vice-versa, acesse a página Outras considerações para saber mais.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Outras considerações
- Efeitos colaterais no Compose
- Dados com escopo local usando o CompositionLocal