findViewById() returns null for custom component in layout XML, not for other components

XmlAndroidLayout

Xml Problem Overview


I have a res/layout/main.xml including these elements and others:

<some.package.MyCustomView android:id="@+id/foo" (some other params) />
<TextView android:id="@+id/boring" (some other params) />

In my Activity's onCreate, I do this:

setContentView(R.layout.main);
TextView boring = (TextView) findViewById(R.id.boring);
// ...find other elements...
MyCustomView foo = (MyCustomView) findViewById(R.id.foo);
if (foo == null) { Log.d(TAG, "epic fail"); }

The other elements are found successfully, but foo comes back null. MyCustomView has a constructor MyCustomView(Context c, AttributeSet a) and a Log.d(...) at the end of that constructor appears successfully in logcat just before the "epic fail".

Why is foo null?

Xml Solutions


Solution 1 - Xml

Because in the constructor, I had super(context) instead of super(context, attrs).

Makes sense, if you don't pass in the attributes, such as the id, then the view will have no id and therefore not be findable using that id. :-)

Solution 2 - Xml

I had the same problem, because in my custom view I have overridden the constructor, but invoked the super constructor without the attrs parameter. (That was a copy/paste mistake.)

My previous constructor version:

public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
    super(context);
}

Now I have:

public TabsAndFilterRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
}

And that works!

Solution 3 - Xml

I had the same problem. My mistake was that: I wrote

		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout=inflater.inflate(R.layout.dlg_show_info, null);
		alertDlgShowInfo.setView(layout);
        TableRow trowDesc=(TableRow)findViewById(R.id.trowDesc);

and as I used an inflater to "load" the view from an XML file, the last line was wrong. To solve it, I had to write:

TableRow trowDesc=(TableRow)layout.findViewById(R.id.trowDesc);

I wrote my solution, in case someone have the same problem.

Solution 4 - Xml

Seems there is a variety of reasons. I just used "Clean..." in Eclipse to solve a similar problem. (FindViewByID had worked before and for some reason started to return null.)

Solution 5 - Xml

Same issue, but different solution: I didn't call

setContentView(R.layout.main)

BEFORE I tried to find the view as stated here

Solution 6 - Xml

If you have multiple layout versions (depending on screen densities, SDK versions) make sure that all of them include the element you are looking for.

Solution 7 - Xml

In my case findViewById was returning null because my custom view looked something like this in the main XML:

		<com.gerfmarquez.seekbar.VerticalSeekBar  
			android:id="@+id/verticalSeekBar"
		    android:layout_width="wrap_content" 
		    android:layout_height="fill_parent" 
		    />

and I found out that when I added the xmlns stuff it worked like this:

		<com.gerfmarquez.seekbar.VerticalSeekBar  
			xmlns:android="http://schemas.android.com/apk/res/android"
			android:id="@+id/verticalSeekBar"
		    android:layout_width="wrap_content" 
		    android:layout_height="fill_parent" 
		    />

Solution 8 - Xml

Be sure that the setContentView(R.layout.main) statement call before findViewById(...) statement;

Solution 9 - Xml

For me, the problem was solved when I added the res folder to the Source in Java Build Path in project Settings.

Solution 10 - Xml

I ran into the same issue a while back when I added a custom View via the layout XML and then tried to attached a callback elsewhere in the application ...

I created a custom view and added it to my "layout_main.xml"

public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback {
	public MUIComponent (Context context, AttributeSet attrs ) {
		super ( context, attrs );
	}
	// ..
}

And in the main Activity I wanted to attach some callbacks and get references to the UI elements from the XML.

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		// ...
		
		MUIInitializer muiInit = new MUIInitializer();
		muiInit.setupCallbacks(this);
		muiInit.intializeFields(this);
	}		
}

The initilizer wasn't doing anything fancy but any changes it tried to make to the custom view (MUIComponent) or other non-custom UI elements simply were not appearing in the application.

public class MUIInitializer {

	// ...
	
	public void setupCallbacks ( Activity mainAct ) {

		
        // This does NOT work properly
		// - The object instance returned is technically an instance of my "MUICompnent" view
		//   but it is a *different* instance than the instance created and shown in the UI screen
		// - Callbacks never get triggered, changes don't appear on UI, etc.
        MUIComponent badInst = (MUIComponent) mainAct.findViewById(R.id.MUIComponent_TESTSURF);

        
 		// ...
 		// This works properly
        
		LayoutInflater inflater = (LayoutInflater) mainAct.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View inflatedLayout = inflater.inflate ( R.layout.activity_main, null );

        MUIComponent goodInst = (MUIComponent) inflatedLayout.findViewById(R.id.MUIComponent_TESTSURF);

        
        // Add callbacks
        // ...
    }

}

The difference between the "badInst" and "goodInst" is:

  • badInst uses the Activity's findViewByID
  • goodInst inflates the layout and uses the inflated layout to do the lookup

Solution 11 - Xml

This happened to me with a custom component for Wear, but is a generic piece of advice. If you're using a Stub (such as I was using WatchViewStub), you can't just put the call to findViewById() anywhere. Everything inside the stub must be inflated first, which doesn't just happen after setContentView(). Thus, you should write something like this in order to wait for that to happen:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_wear);
    final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
        @Override
        public void onLayoutInflated(WatchViewStub stub) {
            myCustomViewInst = (MyCustomView) findViewById(R.id.my_custom_view);
            ...

Solution 12 - Xml

My problem was a typo. I had written android.id (dot) instead of android:id. :P

Apparently there is no syntax check within my custom component xml. :(

Solution 13 - Xml

Had the same problem.

I had layout with few children. From constructor of one them I was trying to get reference (by using context.findViewById) to other child. It wasn't working because the second child was defined further in layout.

I've resolved it like this:

setContentView(R.layout.main);
MyView first = findViewById(R.layout.first_child);
first.setSecondView(findViewById(R.layout.second_child));

It would work as well if the order of children was opposite,but I guess it generally should be done like above.

Solution 14 - Xml

The findViewById() method sometimes returns null when the root of layout has no android:id attribute. Eclipse wizard for generating layout xml file does not automatically generate android:id attribute for the root element.

Solution 15 - Xml

In my case the view was in the parent NOT in the view I was trying to call it in. So in the child view I had to call:

RelativeLayout relLayout = (RelativeLayout) this.getParent();
View view1 = relLayout.findViewById(R.id.id_relative_layout_search);

Solution 16 - Xml

The 'clean' option worked for me.

In my case, the root cause is that the source code resides on a network share, and my workstation and fileserver were not synchronized correctly, and had drifted by 5 seconds. The timestamps on the files created by Eclipse are in the past (because they are assigned by the fileserver) w.r.t. the workstation's clock, causing Eclipse to resolve dependencies between generated and source files incorrectly. In this case, a 'clean' appears to work, because it forces a complete rebuild instead of an incremental build that depends on wrong timestamps.

Once I fixed the NTP settings on my workstation, the problem never occured again. Without proper NTP settings, it would happen every few hours, as the clocks drift fast.

Solution 17 - Xml

To add another trivial mistake to the answers to look out for:

Check that you're actually editing the right layout XML file...

Solution 18 - Xml

i had the same problem because i forgot to update the view id in all my layout folders.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris BoyleView Question on Stackoverflow
Solution 1 - XmlChris BoyleView Answer on Stackoverflow
Solution 2 - XmlAlexander KorolchukView Answer on Stackoverflow
Solution 3 - XmlVincentView Answer on Stackoverflow
Solution 4 - XmljellyfishView Answer on Stackoverflow
Solution 5 - XmlDanielView Answer on Stackoverflow
Solution 6 - XmlM.Q.View Answer on Stackoverflow
Solution 7 - XmlgerfmarquezView Answer on Stackoverflow
Solution 8 - XmlMasonView Answer on Stackoverflow
Solution 9 - XmlJiwon ParkView Answer on Stackoverflow
Solution 10 - XmlDevByStarlightView Answer on Stackoverflow
Solution 11 - XmlStephen WylieView Answer on Stackoverflow
Solution 12 - XmlJOGView Answer on Stackoverflow
Solution 13 - XmlKangurView Answer on Stackoverflow
Solution 14 - XmlSantoshView Answer on Stackoverflow
Solution 15 - XmlMike6679View Answer on Stackoverflow
Solution 16 - XmlditerView Answer on Stackoverflow
Solution 17 - XmlblubView Answer on Stackoverflow
Solution 18 - XmlShanij P.SView Answer on Stackoverflow