如何在Android中以编程方式加载布局XML文件?

MC *_*ror 6 layout android

我创建了一个布局(比如my_layout.xml),其中包括两个其他XML布局文件,比如some_layout.xmlanother_layout.xml.my_layout.xml是使用绘制的setContentView(R.layout.my_layout).

现在我有一个带ID的复选框some_checkbox,它在some_layout.xml中定义,我想给复选框一个OnCheckedChangeListenerusing setOnCheckedChangeListener(),就像这样:

CheckBox cb = (CheckBox) findViewById(R.id.some_checkbox);
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    ...
});
Run Code Online (Sandbox Code Playgroud)

但现在NullPointerException抛出了,因为cbnull.我猜那是因为包含的布局some_checkbox(some_layout)没有加载setContentView(R.layout.some_layout).

  • 问题1:为什么?为什么回归发现R.id.some_checkbox nullsome_layout真的可见的.
  • 问题2:如何"加载" some_layout以便我可以捕获some_layout变量,就像我在上面的代码片段中尝试过的那样?

UPDATE

我终于解决了它,使用以下内容,由stealthjong建议:

一种解决方案可能是初始化checkedChangeListener,向可扩展列表视图添加侦听器,以及打开可扩展列表视图的子项时,检查您Checkbox是否是其中一个膨胀的子项,并添加checkedchangeListenerif if.

我创建了一个名为的方法setCheckedChangeListenerToElement(int resourceId, OnCheckedChangeListener listener),它保存给定的resourceId(它是附加监听器的元素的ID)和给定的监听器.一旦inflater调用该方法getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent),就可以检索View.然后,在该View上,findViewById(int resourceId)可以调用,resourceId复选框的ID 在哪里.

ste*_*ong 21

这有两种方法.

第一个是通过XML添加子布局:

1. XML方法

my_layout.xml

<?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" >

    <include
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        layout="@layout/child_layout1" >
    </include>

    <include
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        layout="@layout/child_layout2" />

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

child_layout1child_layout2只是两个其他布局,第二个有一个ButtonID为mbutton.

您的申请表应如下所示:

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        View v = findViewById(R.id.mbutton);
        System.out.println(v == null);
        System.out.println(v.getClass().getName());
    }   
}
Run Code Online (Sandbox Code Playgroud)

就像我怀疑的那样,这给了我一个false和一个网android.widget.Button.

2.程序化方法

另一种方法是程序化的方法,因为你这样描述,我怀疑这是你做过(或至少试过):

noinclude_layout.xml

<?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" >

    <RelativeLayout
        android:id="@+id/inclusionlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </RelativeLayout>

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

还有一个稍大的应用程序入口点:

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.noinclude_layout);
        ViewGroup inclusionViewGroup = (ViewGroup)findViewById(R.id.inclusionlayout);

        View child1 = LayoutInflater.from(this).inflate(
                R.layout.child_layout1, null); 
        View child2 = LayoutInflater.from(this).inflate(
                R.layout.child_layout2, null);
        inclusionViewGroup.addView(child1);
        inclusionViewGroup.addView(child2);

        View v = findViewById(R.id.mbutton);
        System.out.println(v == null);
        System.out.println(v.getClass().getName());
    }   
}
Run Code Online (Sandbox Code Playgroud)

哪个也给我一个false和一个android.widget.Button.

两种解决方案都应该正常工作.

UPDATE

expandableListView的问题就在于,因为childLayout在实际打开/展开部分之前不会膨胀(请参阅下面的代码,了解一小段代码以检查当前的viewtree).

一种解决方案可能是初始化checkedChangeListener,向可扩展列表视图添加侦听器,以及打开可扩展列表视图的子项时,检查您Checkbox是否是其中一个膨胀的子项,并添加checkedchangeListenerif if.

一个可能更简单的方法是这个:

<CheckBox
    ...
    android:onClick="checkclicked" />
Run Code Online (Sandbox Code Playgroud)

并在您的Activity,添加方法public void checkclicked(View view){ ... }

ViewTree打印机

private void printFullTree() {
    printTree(this.getWindow().getDecorView(),0);
}

private void printTree(View view, int indent) {
    System.out.print(indent(indent) + view.getClass().getName() + "; " + view.getId());
    if (view instanceof ViewGroup) {
        ViewGroup vg = (ViewGroup)view;
        System.out.print("; children = " + vg.getChildCount() + "\n");
        for (int i = 0; i< vg.getChildCount(); i++) {
            printTree(vg.getChildAt(i), indent++);
        }
    }
    else
        System.out.print("\n");
}

private String indent(int indent) {
    String result = "";
    for (int i = 0; i < indent; i++) {
        result += "  ";
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)


Rya*_*yan 9

如果some_layout.xml包含在my_layout.xml中,则使用include标记,例如: -

<include layout="@layout/some_layout" android:id="@+id/someLayoutId" />
Run Code Online (Sandbox Code Playgroud)

然后你可以做到以下几点: -

View someLayoutView = findViewById(R.id.someLayoutId);
CheckBox cb = (CheckBox) someLayoutView.findViewById(R.id.some_checkbox);
Run Code Online (Sandbox Code Playgroud)

如果以编程方式夸大some_layout.xml,例如: -

View someLayoutView = LayoutInflater.from(mContext).inflate(
                    R.layout.some_layout, null);
Run Code Online (Sandbox Code Playgroud)

然后你仍然可以这样做: -

CheckBox cb = (CheckBox) someLayoutView.findViewById(R.id.some_checkbox);
Run Code Online (Sandbox Code Playgroud)