I’ve seen a lot of confusion on how to correctly create headers and footers in Activities with a ScrollView root. There’s also a lot of bad advice lying around, mostly involving RelativeLayout and resulting in headers and footers overlapping other parts of the UI when space is scarce.

We’ll take a look at a better solution using the much more simple LinearLayout.

To be on the same page, let’s agree on how we want our footers and/or headers to behave. First, however, some definitions. Our content, hosted inside a fullscreen ScrollView, will consist of:

  • Header (optional): this View‘s top will match the ScrollView‘s.
  • Body: this View will always be right below the header, and somewhere above the footer.
  • Footer (optional): this View‘s bottom will match the ScrollView‘s

Good! Now, when the body’s content is smaller than the remaining space between the header and the footer, the layout will look like this:

Layout with no scrollbars

Layout with no scrollbars.

Unlike simple fixed headers and footers, however, ours will move out of the way if necessary. If the body’s size exceeds the available space, we want the layout to behave like this:

Layout with scrollbars

Layout with scrollbars. Left: scrolled to top; right: scrolled to bottom

Notice how, now that the screen’s size is not enough to display all of our content, the footer and the header are no longer anchored and respond to scrolling, without overlapping the body.

So, how do we get there? We use LinearLayout‘s layout_weight behavior to ensure that the body area will always expand to be at least as long as the remaining sandwiched space between the header and the footer. If the content’s shorter, it expands until it reaches the footer’s top; if it’s longer, it pushes the footer down.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fillViewport="true">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <!-- HEADER -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
    />

    <!-- BODY -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:orientation="vertical"
    />

    <!-- FOOTER -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
    />
</LinearLayout>
</ScrollView>

VoilĂ !

Obviously, the header and the footer can be omitted. They are not both mandatory, the same technique will work for just a header, or just a footer.

If you’ve read this far, well, I hope this helped you. You are more than welcome to contact me with doubts, suggestions or corrections.

Saludos!

Advertisements