Can anyone help me to find out what can be the issue with this program.
In the onCreate() method the findViewById() returns null for all ids and this causes a null pointer exception later. I can not figure out why the findViewById() can not find the view. Any suggestions?
This is the main code:
public class MainActivity extends Activity {
ViewPager pager;
MyPagerAdapter adapter;
LinearLayout layout1, layout2, layout3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout1 = (LinearLayout) findViewById(R.id.first_View);
layout2 = (LinearLayout) findViewById(R.id.second_View);
layout3 = (LinearLayout) findViewById(R.id.third_View);
adapter = new MyPagerAdapter();
pager = (ViewPager) findViewById(R.id.main_pager);
pager.setAdapter(adapter);
}
private class MyPagerAdapter extends PagerAdapter
{
#Override
public int getCount() {
return 3;
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LinearLayout l = null;
if (position == 0 )
{
l = layout1;
}
if (position == 1)
{
l = layout2;
}
if (position == 2)
{
l = layout3;
}
collection.addView(l, position);
return l;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view==object);
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
}
}
And the related XML files:
activity_main layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#a4c639">
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_pager"/>
</LinearLayout>
activity_first layout:
<?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:id="#+id/first_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/button1"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
activity_second layout:
<?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:id="#+id/second_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
And the activity_third layout:
<?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:id="#+id/third_View">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</LinearLayout>
findViewById() returns a View if it exists in the layout you provided in setContentView(), otherwise it returns null and that's what happening to you. Note that if you don't setContentView(), and don't have a valid view to findViewById() on, findViewById() will always return null until you call setContentView().
This also means variables in the top-level trigger an NPE, because they're called before onCreate(), and by extension, before setContentView(). See also the activity lifecycle
Example if you setContentView(R.layout.activity_first); and then call findViewById(R.id.first_View); it will return a View which is your layout.
But if you call findViewById(R.id.second_View); before setContentView(), it will return null since there is not a view in your activity_first.xml layout called #+id/second_View.
Emphasis added
For those cases within an Activity class.
Activity.findViewById(int id)
Finds a view that was identified by the id attribute from the XML that was processed in onCreate(Bundle).
Otherwise, such as an Fragment, Adapter, a View from a LayoutInflater, etc.
View.findViewById(int id)
Look for a child view with the given id. If this view has the given id, return this view.
Either case,
Returns
The view if found or null otherwise.
Now, re-check your XML files. Make sure you put the right value into setContentView or inflater.inflate.
In the case of an Activity, call findViewById after setContentView.
Then, make sure there is a View you are looking for with android:id="#+id/..." in that layout. Make sure the + is at #+id, which will add the resource to the R.id values to ensure you can find it from Java.
The views you're trying to get are not defined in your activity_main layout. You need to programmatically inflate the views you're trying to add to the pager.-
#Override
public Object instantiateItem(ViewGroup collection, int position) {
LinearLayout l = null;
if (position == 0) {
l = (LinearLayout) View.inflate(this, R.layout.activity_first, null);
}
if (position == 1) {
l = (LinearLayout) View.inflate(this, R.layout.activity_second, null);
}
if (position == 2) {
l = (LinearLayout) View.inflate(this, R.layout.activity_third, null);
}
collection.addView(l, position);
return l;
}
Sometimes you need clean your project in Eclipse (Project - Clean..).
add those views to the pager adapter before accessing them.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new MyPagerAdapter();
pager = (ViewPager) findViewById(R.id.main_pager);
pager.setAdapter(adapter);
layout1 = (LinearLayout) findViewById(R.id.first_View);
layout2 = (LinearLayout) findViewById(R.id.second_View);
layout3 = (LinearLayout) findViewById(R.id.third_View);
}
in the pager adapter:
public Object instantiateItem(View collection, int position) {
if(position == 0){
View layout = inflater.inflate(R.layout.activity_first, null);
((ViewPager) collection).addView(layout);
return layout;
}
... and so forth.
}
from here you can access them via findViewById.
In my case, it was a stupid mistake on my part. I had written code in the OnCreate method but it was above the setContentView line of code. Once I moved my code below this line the application started working fine.
setContentView(R.layout.activity_main);
What #Warlock said above is right , you should initial LinearLayout layout1, layout2, layout3 by the right way:
LinearLayout layout1 = (LinearLayout) View.inflate(this, R.layout.first_View, null);
LinearLayout layout2 = (LinearLayout) View.inflate(this, R.layout.second_View, null);
LinearLayout layout3 = (LinearLayout) View.inflate(this, R.layout.third, null);
wish my advise help you
I have gotten this error today and it was so simple to clear, that I "facepalmed".
Just try to add the UI element to your layout xml File in your res/layout-port directory!!!
In Android, findViewById(R.id.some_id) works when you are finding view in the layout set.
That is, if you have set a layout say:
setContentView(R.layout.my_layout);
Views can be found only in this layout (my_layout).
In your code layout1, layout2, layout3 all are three different layouts and they are not set to the activity.
The findViewById method must find what is in the layout (which you called in the setContentView)
Use the adaptor, to inflate the layout, and based on the position you can search for the view.
override fun instantiateItem(collection: ViewGroup, position: Int) : ViewGroup {
val inflater = LayoutInflater.from(mContext)
val layout = inflater.inflate(mData[position], collection, false) as ViewGroup
if(position == your_position) {
val nameOfField: TextView = layout.findViewById(R.id.item_id)
}
This problem is also generated when you are having same name of many components in XML file. Even if they are different layout files you should give every element a unique name.
This error occur because you are having a XML element with the same name in another layout file and android studio is trying to access that and showing this error
How to add a Footer to a listView with Adapter ?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
I've try this :
public class message extends ListActivity {
List<SMSData2> smsList2 = new ArrayList<SMSData2>();
private Context context = null;
private ListView list = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
list = (ListView)findViewById(android.R.id.list);
//code to set adapter to populate
for (int i=0;; i < 10; i++) {
SMSData2 sms2 = new
sms2.setBody(c.getString("some text");
smsList2.add(sms2);
setListAdapter(new ListAdapter2(this, smsList2));
}
View footerView = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer, null, false);
list.addFooterView(footerView);
}
}
but it returns java.lang.NullPointerException !
possible issues :
bug with the inflater !
Bug with the context !
thanks !
Call the method
addFooterView (View v)
and pass the view you want to add to the listview.
The listview is already having this method.
Have a look on the docs.
simplest solutin is to define a linear layout that has 2 items first is your list view and the second is the footer.
if however you still insist on using a footer by the footer method you do so from activity code:
//after code to set adapter to populate list
View footerView = ((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
list.addFooterView(footerView);
obviously not a profound question, but I think theres probably an error in my approach.
So I've added the file listview.xml to my project in the layout folder.
it contains this:
<?xml version="1.0" encoding="utf-8"?>
<ListView android:id="#+id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
I've also tried:
<?xml version="1.0" encoding="utf-8"?>
<ListView android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
And i my main activity function generally looks like this:
public class ToDoManagerActivity extends ListActivity {
private static final int ADD_TODO_ITEM_REQUEST = 0;
private static final String FILE_NAME = "TodoManagerActivityData.txt";
private static final String TAG = "Lab-UserInterface";
// IDs for menu items
private static final int MENU_DELETE = Menu.FIRST;
private static final int MENU_DUMP = Menu.FIRST + 1;
ToDoListAdapter mAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a new TodoListAdapter for this ListActivity's ListView
mAdapter = new ToDoListAdapter(getApplicationContext());
// Put divider between ToDoItems and FooterView
getListView().setFooterDividersEnabled(true);
// TODO - Inflate footerView for footer_view.xml file
TextView footerView = (TextView) getLayoutInflater().inflate(R.layout.footer_view, null);
// NOTE: You can remove this block once you've implemented the assignment
if (null == footerView) {
return;
}
// TODO - Add footerView to ListView
getListView().addFooterView(footerView);
setListAdapter(mAdapter);
setContentView(R.layout.footer_view);
This keeps breaking with the error:
...java.lang.RunTimeException: content must have a ListView whose id attribute is 'android.R.id.list'
I noticed that if I comment out the setContentView(R.layout.footer_view) bit the error disappears, which is quite confusing as well, because it seems like the error should trigger before there.
This is confusing the hell out of me because as far as I can tell this element exists. Its seems like maybe I'm missing a step to load the ListView? I'm banging my head against the wall here and this seems like something really basic, and being a n00b sucks...So any help is much appreciated!
Cheers!
EDIT:
footer_view.xml contents:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/footerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="#string/add_new_todo_item_string"
android:textSize="24sp" >
</TextView>
EDIT2:
Current onCreate after suggested edits:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create a new TodoListAdapter for this ListActivity's ListView
mAdapter = new ToDoListAdapter(getApplicationContext());
// Put divider between ToDoItems and FooterView
getListView().setFooterDividersEnabled(true);
setListAdapter(mAdapter);
TextView footerView = (TextView) getLayoutInflater().inflate(R.layout.footer_view, getListView(), false);
getListView().addFooterView(footerView);
}
For an Activity that is extending ListActivity, the ListView needs to exist within the xml file that you are using in the activity, in your case that's the footer_view file.
Taken from the Google Dev Site - "ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "#android:id/list""
To incorporate your footer below your list, try this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="#+id/footerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="#string/add_new_todo_item_string"
android:textSize="24sp" >
</TextView>
</LinearLayout>
Here, try this in your layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:id="#android:id/list" />
</LinearLayout>
That is exactly what I have in my app.
Then in your onCreate(), just this:
setContentView(R.layout.activity_main);
Try it and let me know if it works. That code should work. From there, we can continue on to isolate the problem.
EDIT:
Man, now I see your problem. Not a big deal here. Let's look at your code (edited to be shorter). The onCreate() method has this:
super.onCreate(savedInstanceState);
mAdapter = new ToDoListAdapter(getApplicationContext());
getListView().setFooterDividersEnabled(true);
TextView footerView = (TextView) getLayoutInflater().inflate(R.layout.footer_view, null);
getListView().addFooterView(footerView);
setListAdapter(mAdapter);
setContentView(R.layout.footer_view);
Do you see R.layout.activity_main anywhere there? There's your issue! Your R.layout.footer_view only contains a textview, it doesn't contain the ListView, and your Activity keeps looking for the ListView that you promised it that you'd have by extending a ListActivity.
Try this - change your onCreate() method to this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new ToDoListAdapter(getApplicationContext());
setListAdapter(mAdapter);
}
Then your activity_main.xml layout file should look like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"
android:id="#android:id/list" />
</LinearLayout>
This should work. Let me know.
EDIT2:
Now add this to the end of your onCreate() method:
TextView footerView = (TextView) getLayoutInflater().inflate(R.layout.footer_view, null);
getListView().addFooterView(footerView);
Voila! Should work now.
I'm relatively new to Android programming, and am having a problem with inflation. I'm trying to create a simple activity that spits out a few descriptive fields from a previously selected ListView item.
I can access the source data from the ListView without any problems, but the subsequent activity to display the selected data isn't working. Specifically, the following XML layout excerpt (in layout/info.xml) and corresponding code generates an activity that comes up OK, but doesn't display the string "XYZZY" as desired (as indicated above, the string is normally obtained dynamically from the ListView, but is simplified to a hard-coded string for this example).
What am I doing wrong? Here's the XML excerpt:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#color/black"
android:padding="10dp" >
<!-- Info text -->
<TextView
android:id="#+id/infoname"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:gravity="center_horizontal"
android:textColor="#color/white"
android:textSize="24sp" />
...
</RelativeLayout>
And here's the java excerpt:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info);
LayoutInflater li = getLayoutInflater();
View infoView = li.inflate(R.layout.info, null);
TextView name = (TextView) infoView.findViewById(R.id.infoname);
name.setText("XYZZY");
...
}
by setting the contentView() you don't need to do the inflating yourself. The reason you are not seeing your text is that the inflated layout is not added to the view hierarchy.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.info);
TextView name = (TextView) findViewById(R.id.infoname);
name.setText("XYZZY");
...
}
You can't do setContentView(R.layout.info) and inflate in the same activity for the same layout, choose one of the approaches. For your example above there is the right code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater li = getLayoutInflater();
View infoView = li.inflate(R.layout.info, null);
setContentView(infoView);
TextView name = (TextView) infoView.findViewById(R.id.infoname);
name.setText("XYZZY");
...
}
I've got 2 layouts (main.xml and footer_layout.xml) and am trying to append the footer_layout to my listview in main. I can get it to display but it won't set the text when I use tvFooter.setText();
Main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listIssues"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
</LinearLayout>
footer_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="horizontal"
android:gravity="center"
android:layout_gravity="center" >
<TextView
android:id="#+id/footerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textStyle="bold"
android:layout_marginRight="5dip">
</TextView>
</LinearLayout>
MainActivity code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.footer_layout);
//Context context = getBaseContext();
tvFooter = (TextView)findViewById(R.id.footerText);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
View footerView =
((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
mListViewIssues.addFooterView(footerView);
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}
**Note that I removed the code for 'creator' as it wasn't necessary.
This app runs and displays the data but it doesn't display "DBVersion = 3" in the footer like I want.
Any ideas?
this line:
tvFooter = (TextView)findViewById(R.id.footerText);
requires that the view you are finding be "inside" your applications parent layout already.
try moving the findViewById(), and the setText() to after this line:
mListViewIssues.addFooterView(footerView);
Or better yet (and this might actually be neccessary, I am not certain it will work the other way) change it so that you are calling findViewById on one of the views in between the tvFooter and your parent view i.e. the ListView, or the plain View after you inflate it. Like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.footer_layout);
//Context context = getBaseContext();
tvFooter = (TextView)findViewById(R.id.footerText);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
View footerView =
((LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
mListViewIssues.addFooterView(footerView);
tvFooter = (TextView)footerView.findViewById(R.id.footerText);
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}
note the use of footerView.findViewById(), I think you might have better luck if you explicitly call it on the footerView object rather than just from your activity, which is essentially the same as calling it on your activities parent layout.
You shouldn't set footer_layout as activity layout. The right code looks like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Load listview control.
setContentView(R.layout.main);
final Context context = getBaseContext();
mListViewIssues = (ListView)findViewById(R.id.listIssues);
int DBVersion = 3;
View footerView =((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_layout, null, false);
tvFooter = (TextView)footerView.findViewById(R.id.footerText);
tvFooter.setText("DBVersion = " + String.valueOf(DBVersion));
mListViewIssues.addFooterView(footerView);
//add data to listview through adapter.
mListViewIssues.setAdapter(new IssueInfoAdapter(this, creator.queryAll()));
}