AutoInflate: How to easily add header and footer to ListView

Android development is not just coding in Java. It is also a lot of XML layouts. Java part grows and changes very fast. Developers create and maintain many boilerplate reducing techniques and libraries. But XML part stays the same as years ago.

Let’s consider an example of adding header and footer to ListView. To do this developer is required to finish at least these tasks:

  • create an XML layout with ListView - R.layout.listview;
  • create separate XML layout for header - R.layout.header;
  • create separate XML layout for footer - R.layout.footer;
  • set Activity’s content view R.layout.listview;
  • inflate header and footer using LayoutInflater;
  • add header and footer to ListView.

In this blog post I want to share one technique I use to reduce these tasks to minimum.

The key idea behind this is to create single XML for ListView, it’s header and footer. Which view is header or footer is determined by their relative positions to ListView. Then they are automatically removed from container view and added to ListView. Here is how it looks:

<com.kboyarshinov.autoinflate.AutoInflateLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <!-- Header is above ListView -->
    <TextView
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is header"
        />

    <!-- Header and Footer are automatically added to ListView -->
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <!-- Footer is below ListView -->
    <TextView
        android:id="@+id/footer"
        android:layout_width="match_parent"
        android:layout_height="@dimen/list_item_height"
        android:text="This is footer"
        />
</com.kboyarshinov.autoinflate.AutoInflateLayout>

AutoInflateLayout uses View.onFinishInflate() method to implement this idea:

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        for (int position = 0; position < getChildCount(); position++) {
            View child = getChildAt(position);
            if (child instanceof ListView) {
                ListView listView = (ListView) child;
                populateListView(listView, position);
                break;
            }
        }
    }

    private void populateListView(ListView listView, int position) {
        View header = getChildAt(position - 1);
        View footer = getChildAt(position + 1);
        if (header != null) {
            removeView(header);
            header.setLayoutParams(createListViewLayoutParams(header));
            listView.addHeaderView(header);
        }
        if (footer != null) {
            removeView(footer);
            footer.setLayoutParams(createListViewLayoutParams(footer));
            listView.addFooterView(footer);
        }
    }

    private AbsListView.LayoutParams createListViewLayoutParams(View view) {
        final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        return new AbsListView.LayoutParams(layoutParams.width, layoutParams.height);
    }

The last thing developer needs to do is to just Activity’s content view with that single XML and find corresponding views using findViewById method:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview);
        ListView listView = (ListView) findViewById(R.id.listview);
        TextView header = (TextView) findViewById(R.id.header);
        TextView footer = (TextView) findViewById(R.id.footer);
        // rest of code..
    }

AutoInflateLayout is typically just FrameLayout, so any views besides footer and header can be added to it.

Library

AutoInflateLayout is part of AutoInflate library that simplifies common used patterns in view inflation. It is available at MavenCentral (.aar) or Gradle:

    dependencies {
        compile 'com.kboyarshinov:autoinflate:0.1.1'
    }

AutoInflate is available on Github.

Leave a Comment