I have a spinner inside a listview (only in the first row). As an adapter for the spinner I'm trying to use an arrayadapter but everytime I add my strings to the adapter the app crashes. If I just setup the adapter without any strings it works and shows the empty spinner in the first listrow.
My activity:
public class TestView extends Activity implements OnItemClickListener, OnItemSelectedListener
{
private ListView testPersonList;
private DBManager dbManager;
private FileManager fileManager;
private FormularManager formularManager;
private TestPersonListAdapter testPersonListAdapter;
private String testName;
private Bundle configFile;
private String[] languages;
private String aktLanguagecode;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.test_view);
testPersonList = (ListView) findViewById(R.id.test_view_persons_listview);
Intent intent = getIntent();
testName = intent.getStringExtra(ConstantVariables.BUNDLE_TESTTRACK_NAME);
fileManager = new FileManager(this);
formularManager = new FormularManager(this);
configFile = fileManager.readConfigFile(testName);
languages = formularManager.getLanguagesOfOneFormular(configFile.getString(ConstantVariables.BUNDLE_FORMULAR));
dbManager = new DBManager(this, ConstantVariables.TESTTRACKS + testName + ConstantVariables.SERIAL, testName);
testPersonListAdapter = new TestPersonListAdapter(this, dbManager.getTestPersons());
testPersonList.addHeaderView(testPersonListHeader(languages));
testPersonList.setAdapter(testPersonListAdapter);
testPersonList.setOnItemClickListener(this);
}
private View testPersonListHeader(String[] languages)
{
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View header = new View(this);
header = inflater.inflate(R.layout.new_testperson_listrow, null);
Spinner languageSpinner = (Spinner) header.findViewById(R.id.new_testperson_languagespinner);
LanguageSpinnerAdapter spinnerAdapter = new LanguageSpinnerAdapter(this, R.layout.spinner_listrow, languages);
languageSpinner.setAdapter(spinnerAdapter);
languageSpinner.setOnItemSelectedListener(this);
return header;
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
}
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
My list-adapter:
public class TestPersonListAdapter extends BaseAdapter {
private Cursor cursor;
private LayoutInflater inflater;
public TestPersonListAdapter(Context context, Cursor cursor)
{
this.cursor = cursor;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount()
{
return (cursor.getCount() + 1);
}
@Override
public Object getItem(int position)
{
cursor.moveToPosition(position);
return cursor.getString(cursor.getColumnIndex(ConstantVariables.DB_COLUMN_PERSON));
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
itemView = inflater.inflate(R.layout.testperson_listrow, null);
TextView person = (TextView) itemView.findViewById(R.id.testperson_persontext);
TextView categories = (TextView) itemView.findViewById(R.id.testperson_categorytext);
if(cursor.moveToPosition(position-1))
{
person.setText(cursor.getString(cursor.getColumnIndex(ConstantVariables.DB_COLUMN_PERSON)));
}
return itemView;
}
}
My custom arrayadapter
public class LanguageSpinnerAdapter extends ArrayAdapter<String>
{
private String[] languages;
public LanguageSpinnerAdapter(Context context, int resource, String[] objects)
{
super(context, resource, objects);
this.languages = objects;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return super.getDropDownView(position, convertView, parent);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null) {
row = LayoutInflater.from(parent.getContext()).inflate(R.layout.spinner_listrow, parent, false);
}
TextView language_tv = (TextView) row.findViewById(R.id.spinner_row_language);
language_tv.setText(languages[position]);
return row;
}
}
The new_testperson_listrow.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_large_bg_normal_selector" >
<ImageView
android:id="@+id/new_testperson_listicon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:src="@drawable/list_icon_add_testperson_selector" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/new_testperson_listicon"
android:orientation="vertical" >
<TextView
android:id="@+id/new_testperson_addtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Questionaire"
android:textColor="@drawable/list_text_selector"
android:textSize="15pt" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/new_testperson_listicon"
android:orientation="horizontal" >
<TextView
android:id="@+id/new_testperson_languagetext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="30dp"
android:text="Language"
android:textColor="@drawable/list_text_selector"
android:textSize="10pt" />
<Spinner
android:id="@+id/new_testperson_languagespinner"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="@drawable/spinner_dropdown_selector"/>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/new_testperson_listarrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingRight="30dp"
android:src="@drawable/list_icon_arrow_selector" />
</RelativeLayout>
The spinner_listrow.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/spinner_background_selector" >
<TextView
android:id="@+id/spinner_row_language"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingLeft="30dp"
android:paddingRight="30dp"
android:text="test"
style="@style/TextView_normal"/>
</RelativeLayout>
The spinner_background_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false" android:color="@color/textcolor_orange"/>
<item android:state_pressed="true"><shape>
<solid android:color="@color/textcolor_white" />
<padding android:bottom="4dp" android:left="4dp" android:right="4dp" android:top="4dp" />
</shape></item>
<item android:state_pressed="true"><shape>
<solid android:color="@color/textcolor_orange" />
<padding android:bottom="4dp" android:left="4dp" android:right="4dp" android:top="4dp" />
</shape></item>
</selector>
The Log
04-23 17:58:26.484: E/AndroidRuntime(29813): FATAL EXCEPTION: main
04-23 17:58:26.484: E/AndroidRuntime(29813): Process: com.example.questiohmnaire, PID: 29813
04-23 17:58:26.484: E/AndroidRuntime(29813): android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.LayoutInflater.createView(LayoutInflater.java:620)
04-23 17:58:26.484: E/AndroidRuntime(29813): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:669)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:694)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.LayoutInflater.inflate(LayoutInflater.java:469)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
04-23 17:58:26.484: E/AndroidRuntime(29813): at com.example.questiohmnaire.adapter.LanguageSpinnerAdapter.getCustomView(LanguageSpinnerAdapter.java:36)
04-23 17:58:26.484: E/AndroidRuntime(29813): at com.example.questiohmnaire.adapter.LanguageSpinnerAdapter.getView(LanguageSpinnerAdapter.java:28)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:193)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.Spinner.onMeasure(Spinner.java:482)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.measure(View.java:16497)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1052)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.onMeasure(LinearLayout.java:590)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.measure(View.java:16497)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.measure(View.java:16497)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:719)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:455)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.measure(View.java:16497)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.ListView.setupChild(ListView.java:1870)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.ListView.makeAndAddView(ListView.java:1793)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.ListView.fillDown(ListView.java:691)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.ListView.fillFromTop(ListView.java:752)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.ListView.layoutChildren(ListView.java:1630)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.AbsListView.onLayout(AbsListView.java:2091)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.layout(View.java:14817)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.layout(ViewGroup.java:4631)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.layout(View.java:14817)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.layout(ViewGroup.java:4631)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.layout(View.java:14817)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.layout(ViewGroup.java:4631)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.layout(View.java:14817)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.layout(ViewGroup.java:4631)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.View.layout(View.java:14817)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewGroup.layout(ViewGroup.java:4631)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1987)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1744)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1000)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5670)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.Choreographer.doCallbacks(Choreographer.java:574)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.Choreographer.doFrame(Choreographer.java:544)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.os.Handler.handleCallback(Handler.java:733)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.os.Handler.dispatchMessage(Handler.java:95)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.os.Looper.loop(Looper.java:136)
04-23 17:58:26.484: E/AndroidRuntime(29813): at android.app.ActivityThread.main(ActivityThread.java:5017)
04-23 17:58:26.484: E/AndroidRuntime(29813): at java.lang.reflect
The line which causes the error is:
row = LayoutInflater.from(parent.getContext()).inflate(R.layout.spinner_listrow, parent, false);
I appreciate any help. I've tried for hours now to solve this bug but nothing worked... Thanks in advance!
Before fixing what you have, there's something that is a big no-no: Inflating and setting an adapter on getView
when your position = 0. This will definitelly kill the listview performance, mind that whenever getView will be called with "0", you are constantly doing very, very, very heavy stuff. And this will happen everytime the user scrolls.
So you need to restructure your program. The first thing is, that spinner, create & populate it only once. Outside of getView. Then if position==0
you can quickly return it.
Given that you only need the spinner as the first row, let me suggest you to use listView.addHeaderView(view)
. This handy method allows you to define a Header for the ListView that will always be rendered as the first item, thus removing complexity from getView
, that can focus on rendering the normal items instead of doing unorthodox things depending on the position. Be sure to call addHeaderView
before you set the adapter.
If you don't like the Header approach and go your way, there's an additional caveat: You will have to consider the fact that, when the Spinner row 0 exits the screen, that row view will be passed to you in convertView
to render a normal item (aka View
recycling). You will then have to destroy (and later on recreate) the spinner, or implement the different item type methods: getItemTypeCount
, getItemType
... or disaster will happen.
So in resume:
ListView
Spinner
to the ListView
as a Header ViewgetView
. Let getView concentrate on normal ListView
items.You will get a ListView that runs properly!