Reputation: 4532
I have a custom adapter for my list view (extends ArrayAdapter). The list loads fine. However, when I click on an item in my list, i.e. the 5th item in the list, the position in getView is always 0 instead of 5. It crashes because convertView
is no longer null
If it is 0, the header
variable should be initialized to the R.id.listHeaderTv
TextView, but it can't find it and ends up being null.
How do I fix the position
problem and convertView
not being null anymore?
EDIT: After checking onItemClick method, the position is correct. The only problem then is that after the onItemClick method, getView is being called and crashes there because the view is not being inflated.
LOGCAT:
02-27 16:35:25.280: E/AndroidRuntime(6330): FATAL EXCEPTION: main
02-27 16:35:25.280: E/AndroidRuntime(6330): java.lang.NullPointerException
02-27 16:35:25.280: E/AndroidRuntime(6330): at moflow.adapters.CatalogListAdapter.getView(CatalogListAdapter.java:66)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.AbsListView.obtainView(AbsListView.java:1294)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.ListView.makeAndAddView(ListView.java:1727)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.ListView.fillSpecific(ListView.java:1272)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.ListView.layoutChildren(ListView.java:1558)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.AbsListView.onLayout(AbsListView.java:1147)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.View.layout(View.java:7035)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:909)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.View.layout(View.java:7035)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.View.layout(View.java:7035)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.View.layout(View.java:7035)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.ViewRoot.performTraversals(ViewRoot.java:1045)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.os.Handler.dispatchMessage(Handler.java:99)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.os.Looper.loop(Looper.java:123)
02-27 16:35:25.280: E/AndroidRuntime(6330): at android.app.ActivityThread.main(ActivityThread.java:4627)
02-27 16:35:25.280: E/AndroidRuntime(6330): at java.lang.reflect.Method.invokeNative(Native Method)
02-27 16:35:25.280: E/AndroidRuntime(6330): at java.lang.reflect.Method.invoke(Method.java:521)
02-27 16:35:25.280: E/AndroidRuntime(6330): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-27 16:35:25.280: E/AndroidRuntime(6330): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-27 16:35:25.280: E/AndroidRuntime(6330): at dalvik.system.NativeStart.main(Native Method)
Adapter:
@Override
public int getCount() {
return catalog.size();
}
@Override
public View getView( int position, View convertView, ViewGroup parent ) {
View v = convertView;
CatalogItem item = getItem( position );
if ( v == null ) {
LayoutInflater inflater = ( LayoutInflater ) mContext.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
if ( item.header )
v = inflater.inflate( R.layout.sec_header, null );
else
v = inflater.inflate( R.layout.sec_item, null );
}
if ( item.header ) {
TextView header = ( TextView ) v.findViewById( R.id.listHeaderTV );
header.setText( item.name );
header.setEnabled( false );
} else {
TextView sectionItem = ( TextView ) v.findViewById( R.id.listCreatureNameTV );
sectionItem.setText( item.name );
}
return v;
}
Upvotes: 2
Views: 4712
Reputation: 4532
Hm, don't know where Sam's answer went but he was correct about overriding those two methods getItemViewType() and getViewTypeCount(). I also got help from this page: http://androidtrainningcenter.blogspot.com/2012/03/android-listview-with-section-header.html
Here's the code that ended up working for me:
public View getView( int position, View convertView, ViewGroup parent ) {
ViewHolder holder = null;
int type = getItemViewType( position );
if ( convertView == null ) {
holder = new ViewHolder();
switch( type ) {
case TYPE_ITEM:
convertView = inflater.inflate( R.layout.sec_item, null );
holder.tv = ( TextView ) convertView.findViewById( R.id.listCreatureNameTV );
break;
case TYPE_SEPARATOR:
convertView = inflater.inflate( R.layout.sec_header, null );
holder.tv = ( TextView ) convertView.findViewById( R.id.listHeaderTV );
break;
}
convertView.setTag( holder );
} else {
holder = ( ViewHolder ) convertView.getTag();
}
CatalogItem item = getItem( position );
holder.tv.setText( item.name );
return convertView;
}
public static class ViewHolder {
public TextView tv;
}
Upvotes: 1
Reputation: 14274
getView()
is supposed to produce the view to be displayed. To get the click events, you'll want set on OnItemClickListener such as this:
new OnItemClickListener() {
// @Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Toast.makeText(ListRecords.this,"Clicked item: " + position, Toast.LENGTH_LONG).show();
}
});
... and ignore convertView
for the time being.
Upvotes: 2