How to programmatically load XML layout file in Android?

I made a layout (say my_layout.xml ) that programmatically includes two other XML layout files, for example some_layout.xml and another_layout.xml strong>. my_layout.xml is drawn using setContentView(R.layout.my_layout) .

Now I have a flag with the identifier some_checkbox , which is defined inside some_layout.xml , and I want to set the OnCheckedChangeListener flag using setOnCheckedChangeListener() , like this:

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

But now a NullPointerException because cb is null . I assume that since the layout containing some_checkbox (which is some_layout ) is not loading using setContentView(R.layout.some_layout) .

  • Question 1: Why? Why R.id.some_checkbox null search R.id.some_checkbox ? some_layout is really displayed.
  • Question 2: How do I load ' some_layout so that I can write some_layout to a variable, as I tried in the code snippet above?

UPDATE

I finally solved this using the following suggested by stealthjong :

One solution could be to initialize the checkedChangeListener , add a listener to the extensible listview, and when the child of the extensible list is open, check if your Checkbox one of the inflated children and add checkedChangeListener if so.

I created a method called setCheckedChangeListenerToElement(int resourceId, OnCheckedChangeListener listener) that stores the given resourceId (which is the identifier of the element to which the listener joins), and this listener. After the getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) calls the getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) method getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) , you can get a view. Then in this view, you can call findViewById(int resourceId) , where resourceId is the flag identifier.

+6
source share
2 answers

There are two approaches to this.

First adding child layouts via XML:

1. XML approach

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> 

Both child_layout1 and child_layout2 are just two other layouts, the second has 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()); } } 

this disables me false and android.widget.Button , as I suspected.

2. Program approach

Another approach is a programmatic approach, and since you described it as such, I suspect that this is what you did (or at least tried):

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 higher application entry point:

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

Which also binds me to false and android.widget.Button .

Any solution should work fine.

UPDATE

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

One solution would be to initialize the checkedChangeListener , add a listener to the extensible listview, and when the child of the extensible list is open, check if your Checkbox one of the pout children and add checkedChangeListener if so.

Probably a simpler approach would be as follows:

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

and in Activity add the public void checkclicked(View view){ ... } method

ViewTree Printer

 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; } 
+18
source

If some_layout.xml is included in my_layout.xml using the include tag, for example: -

 <include layout="@layout/some_layout" android:id="@+id/someLayoutId" /> 

Then you can do the following: -

 View someLayoutView = findViewById(R.id.someLayoutId); CheckBox cb = (CheckBox) someLayoutView.findViewById(R.id.some_checkbox); 

If you programmed some_layout.xml inflation file, for example: -

 View someLayoutView = LayoutInflater.from(mContext).inflate( R.layout.some_layout, null); 

Then you can do as above: -

 CheckBox cb = (CheckBox) someLayoutView.findViewById(R.id.some_checkbox); 
+7
source

All Articles