如何以编程方式加载在Android的布局XML文件? [英] How to load programmatically a layout XML file in Android?

查看:120
本文介绍了如何以编程方式加载在Android的布局XML文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经做了布局(比如 my_layout.xml ),其中包括编程其他两个XML布局文件,说的 some_layout.xml another_layout.xml my_layout.xml 使用绘制的setContentView(R.layout.my_layout)

I have made a layout (say my_layout.xml) which includes programmatically two other XML layout files, say some_layout.xml and another_layout.xml. my_layout.xml is drawn using setContentView(R.layout.my_layout).

现在我有一个ID some_checkbox ,其内部定义的 some_layout.xml 一个复选框,我想给复选框的 OnCheckedChangeListener 使用 setOnCheckedChangeListener(),就像这样:

Now I have a checkbox with ID some_checkbox, which is defined inside some_layout.xml, and I want to give the checkbox an OnCheckedChangeListener using setOnCheckedChangeListener(), just like this:

CheckBox cb = (CheckBox) findViewById(R.id.some_checkbox);
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    ...
});

不过现在 NullPointerException异常被抛出,因为 CB 。我想这是因为布局包含 some_checkbox (即 some_layout )未使用加载的setContentView(R.layout.some_layout )

But now a NullPointerException is thrown, because cb is null. I guess that's because the layout containing some_checkbox (which is some_layout) is not loaded using setContentView(R.layout.some_layout).

  • 问题1:为什么呢?为什么返回找到 R.id.some_checkbox some_layout 真正的的可见光。
  • 问题2:我如何'负荷' some_layout 这样我就可以捕捉 some_layout 到一个变量,就像我尝试在$ C $上述C段?
  • Question 1: Why? Why returns finding R.id.some_checkbox null? some_layout really is visible.
  • Question 2: How do I 'load' some_layout so I can capture some_layout into a variable, like I tried in the code snippet above?

我终于解决了它,用下面所建议 stealthjong

I've finally solved it, using the following, suggested by stealthjong:

一种解决方案可以初始化的 checkedChangeListener ,添加一个监听到你的扩展列表视图,以及可扩展列表视图的孩子打开时,检查如果你的复选框是膨胀的一个孩子,并添加 checkedchangeListener 如果是的话。

One solution could be initialising the checkedChangeListener, adding a listener to your expandable listview, and when a child of the expandable listview is opened, checking if your Checkbox is one of the inflated children, and adding the checkedchangeListener if so.

我已经创建了一个名为 setCheckedChangeListenerToElement(INT RESOURCEID,OnCheckedChangeListener监听器)的方法,既节约了给定的RESOURCEID(这是元素的ID其中,附加一个监听器向),并且给定的监听器。一旦充气调用方法 getChildView(INT groupPosition,诠释childPosition,布尔isLastChild,查看convertView,ViewGroup中父),该视图可以检索。然后,在该视图中, findViewById(INT RESOURCEID)可以调用,其中 RESOURCEID 是复选框的ID。

I've created a method called setCheckedChangeListenerToElement(int resourceId, OnCheckedChangeListener listener), which saves the given resourceId (which is the ID of the element where to attach a listener to), and the given listener. Once the inflater calls the method getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent), the View can be retrieved. Then, on that View, findViewById(int resourceId) can be called, where resourceId is the ID of the checkbox.

推荐答案

有两种方法这一点。

首先是通过XML添加子布局:

The first being adding child layouts through 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>

child_layout1 child_layout2 只是两个布局,第二个有一个按钮 id为 mbutton

And child_layout1 and child_layout2 are just two other layouts, the second having a Button with id mbutton.

您的应用程序的入口应该是这样的:

Your application entry should look like this:

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

此网我 android.widget.Button ,完全按照我怀疑。

this nets me a false and a android.widget.Button, exactly as I suspected.

2。的程序化方法

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

The other approach is the programmatical approach, and since you described it as such, I suspect this is what you did (or at least tried to):

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>

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

And a slightly larger application entrypoint:

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

这也是网我 android.widget.Button

这两种解决方案应该工作得很好。

Either solution should work just fine.

更新

expandableListView 是问题,因为childLayout不充气,直到你实际打开/展开部分(见$ C $下面的小块$ C $了C C到检查当前viewtree)。

Your expandableListView is the problem, since the childLayout is not inflated until you actually open/expand the section (see code below for small piece of code to check current viewtree).

一种解决方案可以初始化的 checkedChangeListener ,添加一个监听到你的扩展列表视图,以及可扩展列表视图的孩子打开时,检查如果你的复选框是膨胀的一个孩子,并添加 checkedchangeListener 如果是的话。

One solution could be initialising the checkedChangeListener, adding a listener to your expandable listview, and when a child of the expandable listview is opened, checking if your Checkbox is one of the inflated children, and adding the checkedchangeListener if so.

有一个可能更直接的方法是这样:

A probably more straightforward approach would be this one:

<CheckBox
    ...
    android:onClick="checkclicked" />

和您的活动,添加方法公共无效checkclicked(查看视图){...}

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

这篇关于如何以编程方式加载在Android的布局XML文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆