How to load programmatically a layout XML file in Android?

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

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:

  • Dealing with deprecated android.text.ClipboardManager
  • Is there a way to play .flv video files in android app?
  • android: how do i open another app from my app?
  • How to read data from bluetooth barcode scanner Symbol CS3070 to Android Device
  • Android Virtual Device Manager - Webcam0 on 4.4.2 not working
  • Converting of Uri to String
  • CheckBox cb = (CheckBox) findViewById(R.id.some_checkbox);
    cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        ...
    });
    

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

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

    UPDATE

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

    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.

    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.

    Related posts:

    How to crop an image in android?
    DialogFragment.dismiss crashing with NullPointerException
    SlidingDrawer without handle and sliding actions to content
    TabLayout (Android Design Library) Text Color
    How attach private data to android calendar event
    Supporting both landscape orientations in Honeycomb
  • Update Gradle version on Android Studio 2.0
  • Android ==> ListView stay selected?
  • Android Video Circular Buffer with Sound
  • Adb android conflict with Genymotion
  • Handling multiple geofences transition with common area
  • How to use Doxygen plugin in Android Studio?
  • 2 Solutions collect form web for “How to load programmatically a layout XML file in Android?”

    There are two approaches for this.

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

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

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

    2. Programmatical approach

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

    Which also nets me a false and a android.widget.Button.

    Either solution should work just fine.

    UPDATE

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

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

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

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

    If some_layout.xml is included in my_layout.xml using the include tag, such as:-

    <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 inflated some_layout.xml programatically, such as:-

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

    Then you can still do as above:-

    CheckBox cb = (CheckBox) someLayoutView.findViewById(R.id.some_checkbox);
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.