Android Spinner databind using array list

46,716

Solution 1

The ArrayAdapter tries to display your Location-objects as strings (which causes the Hex-values), by calling the Object.toString()-method. It's default implementation returns:

[...] a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.

To make the ArrayAdadpter show something actually useful in the item list, you can override the toString()-method to return something meaningful:

@Override
public String toString(){
  return "Something meaningful here...";
}

Another way to do this is, to extend BaseAdapter and implement SpinnerAdapter to create your own Adapter, which knows that the elements in your ArrayList are objects and how to use the properties of those objects.

[Revised] Implementation Example

I was playing around a bit and I managed to get something to work:

public class Main extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Create and display a Spinner:
        Spinner s = new Spinner(this);
        AbsListView.LayoutParams params = new AbsListView.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
        );
        this.setContentView(s, params);
        // fill the ArrayList:
        List<Guy> guys = new ArrayList<Guy>();
        guys.add(new Guy("Lukas", 18));
        guys.add(new Guy("Steve", 20));
        guys.add(new Guy("Forest", 50));
        MyAdapter adapter = new MyAdapter(guys);
        // apply the Adapter:
        s.setAdapter(adapter);
        // onClickListener:
        s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            /**
             * Called when a new item was selected (in the Spinner)
             */
            public void onItemSelected(AdapterView<?> parent,
                                       View view, int pos, long id) {
                Guy g = (Guy) parent.getItemAtPosition(pos);
                Toast.makeText(
                        getApplicationContext(),
                        g.getName()+" is "+g.getAge()+" years old.",
                        Toast.LENGTH_LONG
                ).show();
            }

            public void onNothingSelected(AdapterView parent) {
                // Do nothing.
            }
        });
    }

    /**
     * This is your own Adapter implementation which displays
     * the ArrayList of "Guy"-Objects.
     */
    private class MyAdapter extends BaseAdapter implements SpinnerAdapter {

        /**
         * The internal data (the ArrayList with the Objects).
         */
        private final List<Guy> data;

        public MyAdapter(List<Guy> data){
            this.data = data;
        }

        /**
         * Returns the Size of the ArrayList
         */
        @Override
        public int getCount() {
            return data.size();
        }

        /**
         * Returns one Element of the ArrayList
         * at the specified position.
         */
        @Override
        public Object getItem(int position) {
            return data.get(position);
        }

        @Override
        public long getItemId(int i) {
            return i;
        }
        /**
         * Returns the View that is shown when a element was
         * selected.
         */
        @Override
        public View getView(int position, View recycle, ViewGroup parent) {
            TextView text;
            if (recycle != null){
                // Re-use the recycled view here!
                text = (TextView) recycle;
            } else {
                // No recycled view, inflate the "original" from the platform:
                text = (TextView) getLayoutInflater().inflate(
                        android.R.layout.simple_dropdown_item_1line, parent, false
                );
            }
            text.setTextColor(Color.BLACK);
            text.setText(data.get(position).name);
            return text;
        }


    }

    /**
     * A simple class which holds some information-fields
     * about some Guys.
     */
    private class Guy{
        private final String name;
        private final int age;

        public Guy(String name, int age){
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }
    }
}

I fully commented the code, if you have any questions, don't hesitate to ask them.

Solution 2

Simplest Solution

After scouring different solutions on SO, I found the following to be the simplest and cleanest solution for populating a Spinner with custom Objects. Here's the full implementation:

Location.java

public class Location{
    public int id;
    public String location;

    @Override
    public String toString() {
        return this.location;            // What to display in the Spinner list.
    }
}    

res/layout/spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textSize="14sp"
    android:textColor="#FFFFFF"
    android:spinnerMode="dialog" />

res/layout/your_activity_view.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">

    <Spinner
        android:id="@+id/location" />

</LinearLayout>

In Your Activity

// In this case, it's a List of Locations, but it can be a List of anything.
List<Location> locations = Location.all();                  

ArrayAdapter locationAdapter = new ArrayAdapter(this, R.layout.spinner, locations);

Spinner locationSpinner = (Spinner) findViewById(R.id.location);
locationSpinner.setAdapter(locationAdapter);



// And to get the actual Location object that was selected, you can do this.
Location location = (Location) ( (Spinner) findViewById(R.id.location) ).getSelectedItem();

Solution 3

Thanks to Lukas' answer above (below?) I was able to get started on this, but my problem was that his implementation of the getDropDownView made the dropdown items just a plain text - so no padding and no nice green radio button like you get when using the android.R.layout.simple_spinner_dropdown_item.

So as above, except the getDropDownView method would be:

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) 
{
  if (convertView == null)
  {
    LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = vi.inflate(android.R.layout.simple_spinner_dropdown_item, null);
  }

  TextView textView = (TextView) convertView.findViewById(android.R.id.text1);
  textView.setText(items.get(position).getName());

  return convertView;
}

Solution 4

Well, am not gonna confuse with more details.

Just create your ArrayList and bind your values like this.

ArrayList tExp = new ArrayList();
for(int i=1;i<=50;i++)
{
    tExp.add(i);
}

Assuming that you have already a spinner control on your layout say with id, spinner1. Add this code below.

Spinner sp = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<String> adp1=new ArrayAdapter<String>this,android.R.layout.simple_list_item_1,tExp);
adp1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sp.setAdapter(adp1);

All the above code goes under your onCreate function.

Solution 5

Thank Lukas, you help me a lot. I d'like to improve your answer. If you just want to access the selected item later, you can use this :

Spinner spn   = (Spinner) this.findViewById(R.id.spinner);
Guy     oGuy  = (Guy)     spn.getSelectedItem();

So you don't have to use the setOnItemSelectedListener() in your initialisation :)

Share:
46,716
janitheshan
Author by

janitheshan

Updated on October 08, 2020

Comments

  • janitheshan
    janitheshan over 3 years

    I have a array list like this:

    private ArrayList<Locations> Artist_Result = new ArrayList<Location>();
    

    This Location class has two properties: id and location.

    I need to bind my ArrayList to a spinner. I have tried it this way:

    Spinner s = (Spinner) findViewById(R.id.SpinnerSpcial);
    ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item, Artist_Result);
    s.setAdapter(adapter);
    

    However, it shows the object's hexadecimal value. So I think I have to set display the text and value for that spinner controller.

    • maaartinus
      maaartinus over 11 years
      As a trivial quick and dirty solution you could simply implement toString() in Locations.
  • janitheshan
    janitheshan almost 13 years
    I'm new to Android application development. So if you can give me some sample code for your given solution I appreciate that.Thanks Lukas Knuth.
  • janitheshan
    janitheshan almost 13 years
    Thank you very much Lukas Knuth your example works fine. Thanks :)))))
  • JehandadK
    JehandadK over 12 years
    the "getViewTypeCount" method is handled incorrectly. For this type of adpater it should return 1. Adapters try to recycle views and if they know that there are more than 1 views it may not recycle them optimally. Read JavaDoc for the method.
  • Tirtha
    Tirtha almost 12 years
    this is really nice, but the only thing that bugs me is @Override public int getItemViewType(int position) { return android.R.layout.simple_spinner_dropdown_item; } does not work.
  • Nemi
    Nemi about 11 years
    Thank you, I have been searching for this for way too long now.
  • Rohit
    Rohit about 10 years
    How to set selected by age item
  • Deepika Rajani
    Deepika Rajani almost 9 years
    Thanks a lot! It helped me too :)