How to use View Stub in android
Asked Answered
C

3

76

I want to use ViewStub in android, so please help me. I have created

ViewStub stub = new ViewStub;
View inflated = stub.inflate(); 

How to use it programmatically?

Coronagraph answered 20/7, 2012 at 10:45 Comment(1)
Here Romain Guy explains it in more details: android-developers.blogspot.de/2009/03/…Abutter
R
131

Like the documentation says, ViewStub is a View that is inflated lazily.

You can declare a ViewStub in an XML file like this:

 <ViewStub android:id="@+id/stub"
           android:inflatedId="@+id/subTree"
           android:layout="@layout/mySubTree"
           android:layout_width="120dip"
           android:layout_height="40dip" />

The android:layout attribute is a reference to the View that will be inflated next to a call of inflate(). So

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

When the method inflate() is invoked the ViewStub is removed from its parent and replaced with the right View (the root view of mySubTree layout).

If you want to do this progammatically then your code should be something like:

ViewStub stub = new ViewStub(this);
stub.setLayoutResource(R.layout.mySubTree);
stub.inflate(); 
Rattail answered 20/7, 2012 at 11:6 Comment(6)
what's the point of ViewStub android:layout_width="120dip" if it's invisible and later it's replaced after inflating?Abutter
My guess is, it is for the rest of the layout to align properlyGoad
How to show inflated view in Android Studio preview?Prism
I got The specified child already has a parent. You must call removeView() on the child's parent first. error can anyone help me?Anatole
@DenisNek There is a issue in the Android issue tracker but nobody has answered it yet. code.google.com/p/android/issues/detail?id=205335Dehnel
define/override the inflate View's id by using the ViewStub's inflatedId. Does it mean it will reset the view's root id with the one with inflated Id.Come
B
29

Simply a ViewStub is used to increase efficiency of rendering layout. By using ViewStub, manually views can be created but not added to view hierarchy. At the runtime, can be easily inflated, while ViewStub is inflated, the content of the viewstub will be replaced the defined layout in the viewstub.

activity_main.xml we defined viewstub but not created first.enter image description here

Simple example gives better understanding,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="create the view stub" />
     <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hide the stub." />

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <ViewStub
            android:id="@+id/stub_import"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:inflatedId="@+id/content_import"
            android:layout="@layout/splash" />
    </RelativeLayout>
</LinearLayout>

At runtime, when we inflate, the content will be replaced with the layout defined in the viewstub.

public class MainActivity extends Activity {

    Button b1 = null;
    Button b2 = null;

    ViewStub stub = null;
    TextView tx = null;

    int counter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        b1 = (Button) findViewById(R.id.btn1);
        b2 = (Button) findViewById(R.id.btn2);
        b1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (stub == null) {     
                    stub = (ViewStub) findViewById(R.id.stub_import);
                    View inflated = stub.inflate();
                    tx = (TextView) inflated.findViewById(R.id.text1);
                    tx.setText("thanks a lot my friend..");
                } 

            }
        });

        b2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (stub != null) {
                    stub.setVisibility(View.GONE);
                }

            }
        });

    }

enter image description here

So, Lets look at again the view hierarchy,

enter image description here

when we inflate the viewstub, it will be removed from the view hierarchy.

Britishism answered 27/5, 2015 at 11:58 Comment(3)
Note: The inflate() method returns the inflated View once complete. so you don't need to call findViewById() if you need to interact with the layout. so stub = (ViewStub) findViewById(R.id.stub_import); tx = (TextView) findViewById(R.id.text1); tx.setText("thanks a lot my friend.."); stub.inflate(); ref:- developer.android.com/training/improving-layouts/…Totipalmate
given that it doesn't support merge within the content view it represents for some completely stupid reason, I think this reason is invalid. It doesn't help with efficient layouts; it makes them worse.Xenolith
@Britishism for the b2 Button you use View.GONE to setVisibility. The Android Developers Blog uses View.INVISIBLE. Can you mention why you used GONE rather than INVISIBLE?Drucill
U
11

Here is an example for show/hide and change data of ViewStub at run time

activity_main.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/buttonShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show View Stub"/>

    <Button
        android:id="@+id/buttonHide"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hide View Stub"/>

    <ViewStub
        android:id="@+id/viewStub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/layout_of_view_stub"
        />

</LinearLayout>

layout_of_view_stub.xml

<TextView
    android:id="@+id/textInViewStub"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="ViewStub Button"
    />

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ViewStub viewStub;
    private Button buttonShow;
    private Button buttonHide;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        buttonShow = findViewById(R.id.buttonShow);
        buttonHide = findViewById(R.id.buttonHide);
        buttonShow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showViewStub();
            }
        });

        buttonHide.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hideViewStub();
            }
        });
    }

    private void showViewStub() {
        if (viewStub == null) {
            viewStub = findViewById(R.id.viewStub);

            // If you want to change data of ViewStub at runtime, you can do like this
            View inflatedView = viewStub.inflate();
            TextView textViewInViewStub = inflatedView.findViewById(R.id.textInViewStub);
            textViewInViewStub.setText("ABC");
        }
        viewStub.setVisibility(View.VISIBLE);
    }

    private void hideViewStub() {
        if (viewStub == null) {
            return;
        }
        viewStub.setVisibility(View.GONE);
    }
}
Uglify answered 24/3, 2018 at 9:27 Comment(1)
easy to understand. Thank youPropylene

© 2022 - 2024 — McMap. All rights reserved.