É 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 a AndroidView
que pode ser composta. AndroidView recebe uma lambda que retorna um
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 { 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 com vinculação de visualizações
Para incorporar um layout XML, use a
AndroidViewBinding
API, que é fornecida pela androidx.compose.ui:ui-viewbinding biblioteca. 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 uma AndroidView em uma lista lenta (LazyColumn, LazyRow,
Pager, etc.), considere usar a AndroidView
sobrecarga 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 a contém é reutilizada no estado em que se encontra, como é o caso das listas lentas.
Essa sobrecarga de AndroidView adiciona dois parâmetros:
onReset- Um callback invocado para indicar que oViewestá prestes a ser reutilizado. Ele precisa ser não nulo para ativar a reutilização da visualização.onRelease(opcional): um callback invocado para indicar que aViewsaiu da composição e não será reutilizada.
@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 AndroidFragment para adicionar um Fragment no Compose.
O AndroidFragment inclui processamentos específicos de fragmentos, como remover o fragmento quando o elemento combinável sai da composição.
Para incluir um fragmento, use o AndroidFragment
combinável. Você transmite uma classe Fragment para AndroidFragment, que adiciona
uma instância dessa classe diretamente à composição. O AndroidFragment também fornece um objeto fragmentState para criar o AndroidFragment com um estado especificado, arguments para transmitir ao novo fragmento e um callback onUpdate que fornece o fragmento da composição. Como muitos outros elementos combináveis integrados, o AndroidFragment aceita um parâmetro Modifier que pode ser usado, por exemplo, para definir a posição dele no elemento combinável pai.
Chame AndroidFragment no Compose da seguinte maneira:
@Composable fun FragmentInComposeExample() { AndroidFragment<MyFragment>() }
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") } }
Broadcast receivers
Para mostrar CompositionLocal e efeitos
colaterais, se um
BroadcastReceiver precisar ser registrado em
uma função combinável, use LocalContext para usar o contexto atual e
rememberUpdatedState e DisposableEffect efeitos colaterais.
@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 */ }
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, essa função 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) } }