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

AttributeWhat It DoesNotes
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 AttributeEffect Inside FrameLayoutExample
android:layout_gravity="center"Center both axesPlay icon on preview
android:layout_gravity="bottom|end"Bottom-right cornerBadge or FAB dock
android:layout_gravity="top|start"Top-left cornerLogo 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

  1. Create a product card with image, gradient scrim, title, and a top-right discount badge.
  2. Add a loading overlay to an existing screen and block touches until data loads.
  3. Make a clickable tile with ripple and a centered icon + label.