Android ViewStub change layouts programmatically

ViVekH picture ViVekH · May 25, 2016 · Viewed 10.9k times · Source

This is my use case:

I want to change my inflated layout at run time, say first I inflate layout a, then after some time I want to show layout B, then layout C etc.

I read somewhere that rather than including layouts in main layout and then hiding/unhiding I should use viewstub and inflate.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ViewStub
        android:id="@+id/layout_stub"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

My issue now is when I inflate the first layout it works fine but the next time when I try to inflate the second layout I get the stub null.

ViewStub stub = (ViewStub) findViewById(R.id.layout_stub);
        stub.setLayoutResource(layoutId);
        View inflated = stub.inflate();

My understanding is the Viewstub is a container in which the layouts are being loaded, if so why am I not getting the ViewStub when trying to load the second layout? (So this means when I inflated the first layout (A) the layout in which the ViewStub was placed was removed completely?)

I'm looking for any pointers to implementing my usecase with Viewstub or alternatives.

Answer

fractalwrench picture fractalwrench · May 25, 2016

A ViewStub is a placeholder, which is replaced by an inflated layout as soon as ViewStub.inflate() is called. It doesn't make sense to call inflate a second time, as the ViewStub will no longer be in the hierarchy. Instead, you should obtain a reference to your LinearLayout, remove its views, and add your second layout as a child.

ViewStub stub = (ViewStub) findViewById(R.id.layout_stub);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
stub.setLayoutResource(layoutId);
stub.inflate(); // inflate 1st layout

ll.removeAllViews(); // remove previous view, add 2nd layout
ll.addView(LayoutInflater.from(context).inflate(secondLayoutId, ll, false));