user2128112
user2128112

Reputation: 299

Findviewbyid returns null. But can access view elements by getting root view and looping through children

I have an activity i want to use to configure a widget but I can't seem to get findViewById() to work. It returns null for all elements.

Here's my layout file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<TextView
    android:name="@+id/testTextView"
    android:text="refresh time (seconds)"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<EditText
    android:name="@+id/testEditText"
    android:text="10"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="number" />
<Button
    android:name="@+id/testButton"
    android:text="Button text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

This is my activity's onCreate method:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_configure_widget);
    Button button = (Button) findViewById(R.id.testButton);
    EditText editText = (EditText) findViewById(R.id.testEditText);
    TextView textView = (TextView ) findViewById(R.id.testTextView);

    button.setText("Button test");
    editText.setText("editText test");
    textView.setText("textView test");
}

Each those elements (button, editText, textView) are null and it throws a NullPointerException when i try set the text. If I comment out those setText lines the correct layout is shown as defined in the xml.

Though it works if i use View v = findViewById(android.R.id.content); to get the root element and grab the child elements from that. Like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_configure_widget);
    View v = findViewById(android.R.id.content); //this is a FrameLayout, I don't know if the container is always a framelayout
    ViewGroup firstChild = (ViewGroup)((ViewGroup)v).getChildAt(0); //this gets my linearlayout
    TextView textView = (TextView)(firstChild.getChildAt(0));
    EditText editText = (EditText)(firstChild.getChildAt(1));
    Button button = (Button)(firstChild.getChildAt(2));

    button.setText("Button test");
    editText.setText("editText test");
    textView.setText("textView test");
}

Using this the layout is shown with the text for each element set to "Button test" "editText test" and "textView test" as expected.

I've cleaned and rebuilt the project. And when debugging i've checked that the resource names are actually resolving to id numbers.

Can anyone explain what's happening? Why isn't my findViewById() working for me?

Upvotes: 0

Views: 667

Answers (2)

Marcus
Marcus

Reputation: 6717

You need to declare the attribute android:id for those views that you would like to access in your code. Therefore, you need to add this attribute to your views in your xml file.

Change your layout.xml file to this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<TextView
    android:id="@+id/testTextView"
    android:text="refresh time (seconds)"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<EditText
    android:id="@+id/testEditText"
    android:text="10"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:inputType="number" />
<Button
    android:id="@+id/testButton"
    android:text="Button text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

Upvotes: 1

laalto
laalto

Reputation: 152907

Your views don't have any ids. Use android:id and not android:name to declare them.

Upvotes: 2

Related Questions