É possível adicionar uma interface com base no Compose a um app já existente que usa um design com base em visualização.
Para criar uma tela totalmente baseada no Compose, faça sua
atividade chamar o método setContent() e transmitir as
funções combináveis que você quer usar.
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
Esse código é parecido com o que você encontraria em um app feito inteiramente com o Compose.
ViewCompositionStrategy para ComposeView
ViewCompositionStrategy
define quando a composição precisa ser descartada. O padrão,
ViewCompositionStrategy.Default,
descarta a composição quando a
ComposeView
subjacente é desanexada da janela, a menos que faça parte de um contêiner de pool, como uma
RecyclerView. Em um app de atividade única que usa apenas o Compose, esse comportamento padrão é
o esperado. No entanto, se você estiver adicionando o Compose gradualmente à sua
base de código, esse comportamento poderá causar perda de estado em alguns cenários.
Para mudar o ViewCompositionStrategy, chame o método setViewCompositionStrategy()
e forneça uma estratégia diferente.
A tabela abaixo resume os diferentes cenários em que você pode usar
ViewCompositionStrategy:
ViewCompositionStrategy |
Descrição e cenário de interoperabilidade |
|---|---|
DisposeOnDetachedFromWindow |
A composição será descartada quando a ComposeView for removida da janela. Foi substituído por DisposeOnDetachedFromWindowOrReleasedFromPool.Cenário de interoperabilidade: * ComposeView, seja o único elemento na hierarquia de visualização ou no contexto de uma tela mista de visualização/Compose (não no fragmento). |
DisposeOnDetachedFromWindowOrReleasedFromPool (padrão) |
Semelhante a DisposeOnDetachedFromWindow, quando a composição não está em um contêiner de pooling, como um RecyclerView. Se estiver em um contêiner de pooling, ele será descartado quando o próprio contêiner for removido da janela ou quando o item for descartado (ou seja, quando o pool estiver cheio).Cenário de interoperabilidade: * ComposeView se é o único elemento na hierarquia de visualização ou no contexto de uma tela mista de visualização/Compose (não no fragmento).* ComposeView como um item em um contêiner de pooling, como RecyclerView. |
DisposeOnLifecycleDestroyed |
A composição será descartada quando o Lifecycle fornecido for destruído.Cenário de interoperabilidade * ComposeView em uma visualização de fragmento. |
DisposeOnViewTreeLifecycleDestroyed |
A composição será descartada quando o Lifecycle de propriedade do LifecycleOwner retornado por ViewTreeLifecycleOwner.get da próxima janela à qual a visualização está anexada for destruído.Cenário de interoperabilidade: * ComposeView em uma visualização de fragmento.* ComposeView em uma visualização em que o ciclo de vida ainda não é conhecido. |
ComposeView em fragmentos (etapa de transição)
Se você quiser incorporar o conteúdo da IU do Compose em um fragmento ou um layout de visualização
já existente, use ComposeView
e chame o método
setContent()
dele. ComposeView é uma View para Android.
Você pode colocar a ComposeView no seu layout XML como qualquer outra View:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
No código-fonte do Kotlin, infle o layout usando o recurso
de layout definido no XML. Em seguida, acesse a
ComposeView usando o ID do XML, defina uma estratégia de composição que funcione melhor para
a View host e chame setContent() para usar o Compose.
class ExampleFragmentXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_example, container, false) val composeView = view.findViewById<ComposeView>(R.id.compose_view) composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } }
Como alternativa, você também pode usar a vinculação de visualizações para acessar referências ao
ComposeView referenciando a classe de vinculação gerada para o arquivo de layout XML:
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
Figura 1. Isso mostra a saída do código que adiciona elementos do Compose a uma
hierarquia de interface de visualização. A mensagem "Hello Android!" é exibida por um
widget TextView. A mensagem "Hello Compose!" é exibida por um
elemento de texto do Compose.
Também será possível incluir uma ComposeView diretamente em um fragmento se a tela cheia
for criada com o Compose, o que permite evitar totalmente o uso de um arquivo de layout XML.
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
Várias instâncias de ComposeView no mesmo layout
Se houver vários elementos ComposeView no mesmo layout, cada um precisará ter um
ID exclusivo para que o savedInstanceState funcione.
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
Os IDs ComposeView são definidos no arquivo res/values/ids.xml:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
Visualizar elementos combináveis no Layout Editor
Também é possível visualizar elementos que podem ser compostos no Layout Editor para seu layout XML
que contém um ComposeView. Isso permite que você veja como os elementos combináveis ficam
em um layout misto de visualizações e do Compose.
Digamos que você queira mostrar o seguinte elemento combinável no Layout Editor. Os
combináveis anotados com @Preview são bons candidatos para visualização no
Layout Editor.
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
Para mostrar esse elemento combinável, use o atributo de ferramentas tools:composableName e
defina o valor como o nome totalmente qualificado do elemento que será visualizado no
layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.compose.ui.platform.ComposeView android:id="@+id/my_compose_view" tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview" android:layout_height="match_parent" android:layout_width="match_parent"/> </LinearLayout>
