Android ViewStub以编程方式更改布局

时间:2016-05-25 15:12:57

标签: android

这是我的用例:

我想在运行时更改我的膨胀布局,首先说我给布局a充气,然后经过一段时间我想要显示布局b,然后布局c等。

我读到的地方不是在主布局中包含布局,而是隐藏/取消隐藏我应该使用viewstub和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>

我现在的问题是当我给第一个布局充气时它工作正常,但下次当我尝试给第二个布局充气时,我得到了存根null。

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

我的理解是Viewstub是一个正在加载布局的容器,如果是的话 为什么我在尝试加载第二个布局时没有得到ViewStub? (所以这意味着当我给第一个布局(A)充气时,放置ViewStub的布局被完全删除了?)

我正在寻找使用Viewstub或替代方案实现我的用例的任何指针

2 个答案:

答案 0 :(得分:4)

ViewStub是占位符,只要调用ViewStub.inflate(),它就会被膨胀的布局替换。由于ViewStub将不再位于层次结构中,因此第二次调用inflate是没有意义的。相反,您应该获得对LinearLayout的引用,删除其视图,并将您的第二个布局添加为孩子。

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));

答案 1 :(得分:0)

是的,我认为您可以轻松地将其替换为另一个ViewStub并以这种方式懒洋洋地扩充您的新布局:

for Java

 public static ViewStub deflate(View view) {
    ViewParent viewParent = view.getParent();
    if (viewParent != null && viewParent instanceof ViewGroup) {
        int index = ((ViewGroup) viewParent).indexOfChild(view);
        int inflatedId = view.getId();
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        ((ViewGroup) viewParent).removeView(view);
        Context context = ((ViewGroup) viewParent).getContext();
        ViewStub viewStub = new ViewStub(context);
        viewStub.setInflatedId(inflatedId);
        viewStub.setLayoutParams(layoutParams);
        ((ViewGroup) viewParent).addView(viewStub, index);
        return viewStub;
    } else {
        throw new IllegalStateException("Inflated View has not a parent");
    }
}

或带扩展名的Kotlin

fun ViewStub.deflate(view: View): ViewStub {
    val viewParent = view.parent

    if (viewParent != null && viewParent is ViewGroup) {
        val index = viewParent.indexOfChild(view)
        viewParent.removeView(view)
        val viewStub = ViewStub(context).apply {
            inflatedId = this@deflate.inflatedId
            layoutParams = this@deflate.layoutParams
        }
        viewParent.addView(viewStub, index)
        return viewStub
    } else {
        throw IllegalStateException("Inflated View has not a parent")
    }
}

查看Runnable with a Parameter