Question

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!

Was it helpful?

Solution

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:

  • Create your spinner normally, at the same level you create your ListView
  • Add the Spinner to the ListView as a Header View
  • Remove all complexity related to the spinner from getView. Let getView concentrate on normal ListView items.

You will get a ListView that runs properly!

OTHER TIPS

You created a custom layout for the spinner, so you need to create a custom adapter extending ArrayAdapter or something like that.

Or, if you want to show just a list with a single TextView, you don't need to specify a custom layout, just use:

ArrayAdapter<String> adapter = ArrayAdapter.createFromResource(context, <your_string_array_in_xml>, android.R.layout.simple_spinner_item);

or

ArrayAdapter<String> adapter = new ArrayAdapter(context, android.R.layout.simple_spinner_item, <your_string_array>);

If you really need to make a custom Spinner, just follow this link, sure it'll help you: http://mrbool.com/how-to-customize-spinner-in-android/28286

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top