Different views for spinner and spinner item?

Martyn picture Martyn · Sep 21, 2011 · Viewed 12.6k times · Source

Is there any way I can set a different view for the closed spinner view and the spinner item view?

I assume that the resource id used in the ArrayAdapter would be used for the closed item view, as well as the item views, so I extended the ArrayAdapter and defined the getView which uses a different resource, but the resource id in the call to the super constructor doesn't seem to be used ever, only the resource id used in getView seems to be used

In the Spinner.java code it states:

A spinner adapter allows to define two different views: one that shows the data in the spinner itself and one that shows the data in the drop down list when the spinner is pressed.

but it doesn't seem possible given the code.

Anyway - my code:

public class CustomArrayAdapter <T> extends ArrayAdapter<T> {

    int itemViewResourceId;
    private LayoutInflater inflater;
    ViewPopulator<T> viewPopulator;
    private List<T> objects;

    public CustomArrayAdapter(Context context, int textViewResourceId, int itemViewResourceId, ViewPopulator<T> viewPopulator, List<T> objects) {
        super(context, textViewResourceId, objects);
        inflater = LayoutInflater.from(context);
        this.viewPopulator = viewPopulator;
        this.itemViewResourceId = itemViewResourceId;
        this.objects = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null || convertView.getTag() == null) {
            // new view - populate 
            convertView = inflater.inflate(itemViewResourceId, parent, false);
            convertView.setTag(new Object());
        }
        viewPopulator.populateView(position, convertView, parent, objects.get(position));
        return convertView;
    }
}

public abstract class ViewPopulator<T> {
    public abstract void populateView(int position, View convertView, ViewGroup parent, T item);
}

called with:

CustomArrayAdapter<T> typeAdapter = new CustomArrayAdapter<T>(context, R.layout.list_item, R.layout.list_item_big, new ViewPopulator<T>() {
        @Override
        public void populateView(int position, View convertView, ViewGroup parent, T item) {
            ((TextView) convertView.findViewById(R.id.list_item)).setText(position + " - " + item.getName());
        }
    }, itemsByType.get(type));

** EDIT **

The resource id used is the itemViewResourceId defined in the getView method - adding a new method to CustomArrayAdapter, overriding getDropDownView as below give me the same results of the itemViewResourceId being used for all the styling, and the textViewResourceId not being used at all. However, removing the getView results in the textViewResourceId being used - hence I don't think that getDropDownView actually does anything:

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        if(convertView == null || convertView.getTag() == null) {
            // new view - populate 
            convertView = inflater.inflate(itemViewResourceId, parent, false);
            convertView.setTag(new Object());
        }
        viewPopulator.populateView(position, convertView, parent, objects.get(position));
        return convertView;
    }

Answer

Ian picture Ian · Oct 24, 2011

If you implement SpinnerAdapter does that help? The following code works for me:

private class CustomSpinnerAdapter extends BaseAdapter implements SpinnerAdapter {
        String[] values;
        Context context;

        public NumberSpinnerAdapter(String[] values) {
            this.values = values;
            this.context = context;
        }

        @Override
        public int getCount() {
            return values.length;
        }

        @Override
        public Object getItem(int position) {
            return values[position];
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView textView = (TextView) View.inflate(context, android.R.layout.simple_spinner_item, null);
            textView.setText(values[position]);
            return textView;
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            TextView textView = (TextView) View.inflate(context, android.R.layout.simple_spinner_dropdown_item, null);
            textView.setText(values[position]);
            return textView;
        }
    }