FrameLayout (Java) — Overlays, Foreground & Fragment Host
FrameLayout is a minimal container that stacks children in drawing order: the last child in XML appears on top. It’s perfect for overlays (text on image, badges), lightweight cards, and as a fragment container.
Mental Model (Diagram)
Child 1 (bottom)
Child 2
Child 3 (topmost)
Z-order follows XML order → later = on top
When to Use / When to Avoid
| Use FrameLayout for… | Avoid / Consider Alternatives |
|---|---|
|
• Image with label/gradient overlay • Corner badge on thumbnails • Fragment host container • Loading/progress overlay on content • Simple “card” with one primary child |
• Complex alignment → use ConstraintLayout • Long lists → use RecyclerView • Multiple rows/columns → Linear/ConstraintLayout |
Key Attributes
| Attribute | What It Does | Notes |
|---|---|---|
| android:foreground | Drawable drawn over children | Great for ripple (?attr/selectableItemBackground) or dim scrim |
| android:foregroundGravity | Positions the foreground | center, top|end, etc. |
| android:measureAllChildren | Measure even GONE children | Rare; default false |
| android:layout_gravity | How this child sits inside parent | On the child view; e.g., bottom|end |
| android:clipToPadding / clipChildren | Clip drawing to padding or to parent bounds | For fancy overlays/shadows, sometimes set to false |
Example 1 — Hero Image + Gradient + Title (3 Layers)
<!-- res/layout/hero_banner.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="220dp">
<!-- Layer 1: Image -->
<ImageView
android:src="@drawable/banner_city"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Layer 2: Gradient scrim (bottom to top) -->
<ImageView
android:src="@drawable/scrim_bottom"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Layer 3: Text overlay -->
<TextView
android:text="Explore Destinations"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="22sp"
android:layout_gravity="bottom|start"
android:layout_margin="12dp"
android:background="#66000000"
android:padding="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
Why it works: Image (bottom) → scrim (middle) → text (top).
layout_gravity places the text at bottom|start inside the FrameLayout.
Example 2 — Thumbnail with Corner Badge
<!-- res/layout/thumb_badge.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="96dp"
android:layout_height="96dp">
<ImageView
android:src="@drawable/product_thumb"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:text="NEW"
android:textColor="@android:color/white"
android:background="@drawable/bg_badge_red"
android:padding="4dp"
android:layout_gravity="top|end"
android:layout_margin="6dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
Example 3 — Center Play Button Over Preview
<!-- res/layout/video_preview.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp">
<ImageView
android:src="@drawable/video_thumb"
android:scaleType="centerCrop"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:src="@drawable/ic_play"
android:layout_gravity="center"
android:layout_width="48dp"
android:layout_height="48dp" />
</FrameLayout>
Example 4 — Loading Overlay (Disable Touch Underneath)
<!-- res/layout/content_with_loading.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/flRoot"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Bottom: your actual content layout -->
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:text="Products" ... />
<!-- More content -->
</LinearLayout>
<!-- Top: full-screen loading block -->
<FrameLayout
android:id="@+id/loadingOverlay"
android:background="#66000000"
android:clickable="true"
android:focusable="true"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
</FrameLayout>
// Java: show/hide overlay
private void showLoading(boolean show){
View overlay = findViewById(R.id.loadingOverlay);
overlay.setVisibility(show ? View.VISIBLE : View.GONE);
}
Example 5 — Fragment Container + Transaction (Java)
<!-- res/layout/activity_main.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
// MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new HomeFragment())
.commit();
}
}
}
Example 6 — Clickable Card with Ripple via Foreground
<!-- res/layout/clickable_card.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:clickable="true"
android:focusable="true"
android:foreground="?attr/selectableItemBackground"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="Open Details"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
Note: android:foreground sits above children; perfect for ripple feedback without extra views.
Layout Gravity Cheatsheet (Child → Parent)
| Child Attribute | Effect Inside FrameLayout | Example |
|---|---|---|
| android:layout_gravity="center" | Center both axes | Play icon on preview |
| android:layout_gravity="bottom|end" | Bottom-right corner | Badge or FAB dock |
| android:layout_gravity="top|start" | Top-left corner | Logo pin |
Performance & Best Practices
- Keep it shallow: FrameLayout is lightweight; don’t nest many levels without reason.
- Order matters: Place overlays after base content in XML to appear on top.
- Touch blocking: For modal overlays, set clickable/focusable on the top layer.
- Accessibility: Add content descriptions to imagery; ensure overlays have sufficient contrast.
Practice Tasks
- Create a product card with image, gradient scrim, title, and a top-right discount badge.
- Add a loading overlay to an existing screen and block touches until data loads.
- Make a clickable tile with ripple and a centered icon + label.