Sid
Sid

Reputation: 9536

How to "deflate" a ViewStub?

So I can inflate a ViewStub at runtime. Let's say I want to make it disappear and then maybe inflate again depending on some event occurring (for example, a toolbar that inflates and deflates according to what the user selects on screen).

I can use View.setVisibility(View.GONE).... is there any other way?

Or am I doing something wrong here?

Thanks! :)

Upvotes: 29

Views: 14852

Answers (3)

Tom Rutchik
Tom Rutchik

Reputation: 1702

Here's some code that deflates a view stub:

private Boolean isErrorViewInflated = false;
private ViewStub errorViewStub;  
/* here a method that gets a view.  If the view is already inflated,
 * it uses that view, else it inflates the view. It also creates a viewStub
 * object which will be used to replace the inflated view when it needs to 
 * be deflated.
 /
public RelativeLayout getErrorView() {
    RelativeLayout errorView = null;
    if (isErrorViewInflated) {
        errorView = activity.findViewById(R.id.error_view);
    } else {
        ViewStub stub = activity.findViewById(R.id.error_view_stub);
        errorView = (RelativeLayout) stub.inflate();
        errorViewStub = new ViewStub(getContext(), stub.getLayoutResource());
        isErrorViewInflated = true;
    }
    return errorView;
}

/* Here's the code that deflates an inflated ErrorView back to a ViewStub
 */
private void deflateErrorView() {
    if (isErrorViewInflated) {
        RelativeLayout errorView = activity.findViewById(R.id.error_view);
        ViewGroup parent = (ViewGroup)errorView.getParent();
        int index = parent.indexOfChild(errorView);
        parent.removeView(errorView);
        parent.addView(errorViewStub, index);
        isErrorViewInflated = false;
    }
}

If you're wondering, you can't just cache the original ViewStub and use it to replace the inflated view. That's because the original ViewStub object had a parent View and you get an error if you try to add that view into any view group (even if it's the same view group it was originally contained in). So, the way around this issue is to create a new ViewStub object using the same layout resource as in the original ViewStub.

If you're not concerned about the space occupied by an inflated ViewStub when that inflated ViewStub is no longer needed, then the "View.GONE" solution is fine. There's no significant runtime overhead for views whose visibility is set to GONE. In my case, I've been using ViewStub's for errors, logs and console display areas and I want the system to be able to garbage collect the objects associate with those views when they are not in use.

Upvotes: 1

Tofeeq Ahmad
Tofeeq Ahmad

Reputation: 11975

Yes you can remove whenver you want .i have done it just now.

ViewStub stub = findById(...);
View v = stub.inflate();

and set view visibility on any event.

v.setVisibility(View.GONE);

Upvotes: 0

adamp
adamp

Reputation: 28932

Inflating layouts can be expensive, especially on older devices. Think of ViewStub as more of a lazy-loading mechanism for view subtrees that may or may not ever get expanded rather than a way to swap out sections of a view hierarchy at runtime. Once inflated, there's nothing wrong with swapping between VISIBLE/GONE. GONE will make the framework skip that subtree during expensive traversals.

This is true as long as you don't need the memory used by the inflated view. Setting visibility to GONE doesn't release any memory whatsoever; it only marks the view as gone for layout and drawing purposes. To release the memory of the viewstub's inflated view, you would have actually to remove the inflated view and replace it again with a new viewstub for future use.

Upvotes: 37

Related Questions