Aprenda os conceitos-chave do FrameLayout — a ViewGroup mais simples no Android SDK, projetada para hospedar um único elemento filho (normalmente) ou sobrepor vários elementos uns sobre os outros. O FrameLayout é conveniente para contêineres placeholder, fragmentos, indicadores de carregamento e elementos de primeiro plano. Ele não gerencia o posicionamento dos filhos — cada elemento subsequente é desenhado sobre o anterior, e sua posição é determinada por layout_gravity (left, top, right, bottom, center). Os cenários básicos estão descritos na Referência da API FrameLayout.
Principais conclusões
FrameLayout é a ViewGroup mais simples do Android SDK, projetada para bloquear uma área da tela e exibir uma única view filha (ou sobrepor várias). Ao contrário do LinearLayout (disposição sequencial) e RelativeLayout (posicionamento relativo), o FrameLayout não altera as posições dos filhos — cada novo filho é colocado no canto superior esquerdo (0,0) por padrão e desenhado sobre o anterior.
O FrameLayout foi introduzido na API Level 1 e continua sendo o contêiner Android mais leve: ele não substitui onMeasure com lógica complexa e realiza um número mínimo de operações de layout. De acordo com o Android Performance Blog, o FrameLayout executa onLayout em uma única passagem e praticamente não adiciona sobrecarga em comparação com colocar uma View diretamente. Isso o torna uma escolha ideal para contêineres onde a velocidade importa: layouts de itens RecyclerView (combinados com ConstraintLayout para posicionamento), contêineres de Fragment, camadas de sobreposição.
O tamanho do FrameLayout por padrão é determinado pelo maior elemento filho (se match_parent não for definido). Se nenhum filho for especificado, o FrameLayout se contrai para (0,0). O atributo android:measureAllChildren (seção abaixo) altera esse comportamento.
FrameLayout herda de ViewGroup e é o pai direto de muitos contêineres especializados: FragmentContainerView (fragmentos), CardView (cartões com sombra), ScrollView (filho único), NestedScrollView. Ao criar uma Activity com navegação por Fragment, o modelo padrão do Android Studio usa FrameLayout (ou FragmentContainerView) como contêiner raiz para fragmentos.
android:foreground — um atributo FrameLayout que especifica um drawable desenhado sobre todos os elementos filhos. Ao contrário de background (sob os filhos), o foreground é exibido acima do conteúdo e pode ser transparente. É usado para: efeitos de sobreposição ao pressionar (ripple via ?attr/selectableItemBackground), mascaramento de imagens, exibição de indicadores de status (marca de seleção sobre uma imagem).
Foreground suporta recursos drawable padrão: ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. Desde a API 23+, android:foregroundGravity está disponível para posicionamento do foreground (fill, center, top, bottom). No modo fill, foreground se estende por todo o FrameLayout; no modo center, desenha-se no centro.
android:measureAllChildren — um atributo booleano (true por padrão) que determina se todos os elementos filhos devem ser medidos ao calcular o tamanho do FrameLayout. Se true (padrão), o FrameLayout considera os tamanhos de todos os filhos, incluindo GONE (com tamanho 0). Se false, o FrameLayout mede apenas filhos VISIBLE e INVISIBLE — elementos GONE são excluídos do cálculo. De acordo com o Google I/O 2019, desativar measureAllChildren para contêineres com muitos elementos GONE (por exemplo, listas com alternância de visibilidade) acelera o desenho inicial em 20–60%.
android:layout_gravity — um atributo de um elemento filho do FrameLayout (e outros ViewGroups) que define sua posição dentro do contêiner. No FrameLayout, layout_gravity é a única maneira de controlar a posição de um elemento filho, já que o FrameLayout não fornece suas próprias regras de posicionamento (como RelativeLayout) ou direção (como LinearLayout).
Valores possíveis: top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. Combinados via |: android:layout_gravity="bottom|center_horizontal" — o elemento é fixado na borda inferior e centralizado horizontalmente. Para elementos menores que o FrameLayout, layout_gravity determina sua posição no espaço livre.
Se layout_gravity não for definido, o elemento é colocado no canto superior esquerdo (top|left) por padrão. Para um FrameLayout contendo vários filhos, cada um pode ter seu próprio layout_gravity — um elemento pode estar no canto superior esquerdo, outro no canto inferior direito, um terceiro centralizado. Isso permite criar sobreposições simples (por exemplo, um ícone de fechar sobre uma imagem).
android:gravity (atributo pai) alinha o conteúdo dentro do FrameLayout — por exemplo, texto dentro de um TextView. android:layout_gravity (atributo filho) alinha o próprio elemento dentro do FrameLayout. No contexto do FrameLayout, gravity define como os filhos são posicionados por padrão (semelhante a layout_gravity para todos os filhos de uma vez), mas o layout_gravity de cada elemento específico substitui o valor do pai.
Uma imagem com um rótulo de texto no canto inferior direito. FrameLayout contém um ImageView preenchendo a tela e um TextView com layout_gravity="bottom|end" para posicionamento sobre a imagem.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/product_photo"
android:scaleType="centerCrop" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="8dp"
android:background="@drawable/badge_background"
android:elevation="2dp"
android:paddingHorizontal="8dp"
android:paddingVertical="4dp"
android:text="-30%"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
</FrameLayout>
O ImageView preenche todo o FrameLayout (altura de 200dp). O TextView com layout_gravity="bottom|end" é colocado no canto inferior direito sobre a imagem. elevation=2dp adiciona uma sombra sob o rótulo, separando-o visualmente da imagem. Este exemplo mínimo exigiria um contêiner aninhado ou código personalizado no LinearLayout.
Uma tela com conteúdo e uma barra de progresso centralizada que aparece durante o carregamento. FrameLayout contém dois elementos: conteúdo e um ProgressBar com visibility="gone" (alternado no código).
<FrameLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/content_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Conteúdo carregado"
android:textSize="18sp" />
<ProgressBar
android:id="@+id/loading_spinner"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
O ProgressBar está oculto por padrão (gone). Quando o carregamento começa, findViewById(R.id.loading_spinner).visibility = View.VISIBLE é chamado — o spinner aparece centralizado sobre o conteúdo. Após o carregamento — .visibility = View.GONE. FrameLayout fornece sobreposição sem deslocar a posição do conteúdo — o texto não se move quando o spinner aparece, pois o ProgressBar desenha por cima.
FrameLayout como contêiner padrão para FragmentTransaction. A atividade substitui fragmentos dentro deste contêiner conforme a navegação.
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
import androidx.fragment.app.FragmentTransaction
val fragmentContainer = R.id.fragment_container
fun navigateTo(fragment: Fragment) {
supportFragmentManager
.beginTransaction()
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.replace(fragmentContainer, fragment)
.addToBackStack(null)
.commit()
}
FrameLayout como contêiner de fragmentos é a maneira mais leve de suportar a navegação por Fragmentos. FragmentContainerView (subclasse de FrameLayout) é recomendado com Navigation Component 2.4+, mas um FrameLayout simples permanece válido para FragmentTransactions manuais. A principal vantagem é que FragmentTransaction.replace() substitui completamente o conteúdo sem afetar a Activity.
FrameLayout é ideal para quatro cenários: contêiner de fragmentos (FragmentContainerView ou FrameLayout), sobreposição de carregamento (ProgressBar sobre conteúdo), rótulos em cartões (rótulo em imagem), contêiner placeholder para ViewStub (carregamento lento).
Não é adequado para: posicionamento complexo de vários elementos (use ConstraintLayout), listas sequenciais (LinearLayout ou RecyclerView), layouts dinâmicos com alteração de ordem dos elementos.
FrameLayout como elemento raiz da tela — prática ruim se a tela contiver mais de 2–3 elementos. Para um contêiner raiz, use ConstraintLayout — ele dá mais controle sobre o posicionamento sem perda de desempenho. Use FrameLayout apenas para blocos filhos onde seja necessária sobreposição ou placeholder.
Perguntas frequentes
FrameLayout — um contêiner minimalista sem sistema de posicionamento (apenas layout_gravity), projetado para sobreposição de elementos. ConstraintLayout — um sistema de layout completo com constraints, cadeias, barreiras, dimensões percentuais e suporte a MotionLayout. FrameLayout é mais rápido para casos simples (1 filho ou sobreposição); ConstraintLayout é necessário para layouts complexos. Escolha: FrameLayout para sobreposição de carregamento e contêiner de fragmentos; ConstraintLayout para todo o resto.
Defina o tamanho do FrameLayout como wrap_content no eixo desejado (android:layout_width="wrap_content" e/ou android:layout_height="wrap_content"). O FrameLayout então se ajustará ao tamanho do maior elemento filho. Se todos os filhos forem menores que o FrameLayout, o espaço excedente permanece vazio. Para controle preciso, use match_parent com padding fixo.
Este é o comportamento pretendido do FrameLayout — ele não distribui os filhos no espaço, mas os desenha sequencialmente uns sobre os outros. Se você quiser que os elementos não se sobreponham, use outro contêiner (LinearLayout, ConstraintLayout). Para sobreposição parcial com controle da ordem de desenho, use layout_gravity para deslocamento e elevation para ordem Z.
FrameLayout é mais rápido para os casos mais simples — um elemento filho, sem posicionamento complexo. FrameLayout executa onMeasure em tempo mínimo sem calcular constraints. No entanto, a diferença é perceptível apenas em centenas de repetições (RecyclerView com dezenas de milhares de itens). Para uma tela típica (1–3 FrameLayouts), a diferença é de microssegundos e não afeta a UX. ConstraintLayout é a escolha universal para 95% das tarefas.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também