Click here to download the example program.
In order to understand the trick, one has to know, how Adapters work in general and ArrayAdapter in particular. Adapters are objects that are able to turn data structures into widgets. The widgets are then displayed in a List or in a Spinner. So the two questions an Adapter answers are:
- What widget or composite view to associate with a data structure with a certain index.
- How to extract data from the data structure and how to set field(s) of the widget or composite view according to this data.
- Each widget for any index is the same and is inflated from the resource whose ID the ArrayAdapter receives in its constructor.
- Each such a widget is expected to be an instance of TextView (or descendant). The widget's setText() method will be used with the string format of the item in the supporting data structure. The string format will be obtained by invoking toString() on the item.
19 comments:
Hi,
Great explanation!!!
I would also like to point out that instead of maintaining the array of MyData, you could take it out from the initialization of the adapter and add items after the initialization. You could then use the adapter's getItem method to get the selected item.
ArrayAdapter<MyData> adapter =
new ArrayAdapter<MyData>(
this,
android.R.layout.simple_spinner_item);
adapter.add(new MyData("key1", "value1"));
adapter.add(new MyData("key2", "value2"));
adapter.add(new MyData("key3", "value3"));
To retrieve the selected item in the onItemSelected method in the listener:
MyData d = adapter.getItem(position);
Thank you very much for your time. This has helped me a lot.
SunD
Thanks for explaining it. I need to do something little different.
I want spinner lable to always say a constant string say "More...". When you click on it, it needs to show array (as usual) and on select of any item in it, display "More..." on the screen instead of displaying label of selected item. How do I do this?
Hi, Amit,
The standard Spinner implementation does not allow you to do this because the Adapter backing the dropdown list is derived from the Adapter that is backing the Spinner view itself. This can be easily changed, however.
Create a custom view based on the platform's Spinner class.
Source of the Spinner class
Then modify the source in such a way that the adapter backing the Spinner and the adapter backing the dropdown list are separated.
setPrompt(CharSequence prompt) i think u may use it after perfoming click..
This has helped me loads in my latest app createion.
How can I get the spinner to remember what it was set to once the app ic closed?
can I and something to my onDestroy()
Many thanks
Meblin
Thanks for the help!
Just to finalize what Anonymous (SunD) wrote in the first message, the proper way to get the data in the event listener would be:
SpinnerData d = (MyData)parent.getAdapter().getItem(position);
Thanks for the explanation. This is all very straight forward for these purposes, but I wonder if there isn't a way to accomplish this while still populating the spinner with items from an external XML? This question probably has more to do with basic java literacy than with the way a spinner works...
agitcraft, I am not sure I understand your question. If you want to populate the spinner from external XML, all you have to do is to create the data items behind the spinner from the XML file. Android has DOM, SAX and Pull parsers built in from API version 1 so this should not be a problem.
To pick up where agitcraft left off, I think what we're looking for is a way to define such an array in the resources xml files (same as you would do with a string array for a "regular" spinner). I mean an array where the element type is MyData.
Does anyone have such an example?
Exactly what I was looking for. Thanks for posting.
hi,
this is very good tutorial for spinner , who have created his own data . this very much useful for me
very good.
First Thanks a lot for this piece of code.
I have a question I would be very happy if someone can lead me to some directions. I am not a hardcore developer more of a designer.
The Q: I am working with a database and I have a spinner with some clients name; I show the client name as the "value" and the client database ID as the "key". I then store the "key" into some other table in the database in case the user changes the client's name.
When the user wants to modify the data I need to get from the number Id of the client the proper position in the spinner.
I was doing it fine with getPosition(String) but with this new Adapter you have I cannot get the position I always get a -1. I can not return to the normal ArrayAdapter because I need to be able to store the "key" and the "value" provided by your class.
What should i do?
Do I make myself clear. my english is not so good.
Thank you very much
Juan Pablo, getPosition's prototype is exactly:
int getPosition(T item)
This means that if you template ArrayAdapter, then you have to pass a MyData instance as getPosition input argument. That's not enough, you have to implement an equals() method in MyData. Read this tutorial about the equals() method..
When you implement equals() you have to decide when you consider two MyData objects equal. If I understand correctly, you want to search by database IDs so you should consider two MyData instances equals if their database ID fields are equal.
After selecting spinner item entering into the next view but when we write onitem click listener for this first time when we run the app it'll automatically goes to the next view.
but it needs to go after we selecting the item how can i solve this problem.
there is a way to change the renderer of the spinner as it is in Java Swing? Do I necessary have to take care of the "toString" method or there is a more flexible way?
Anonymous, toString() is only relevant if you use ArrayAdapter. There are a bunch of other Adapters available and you can easily write your own.
Hey. this works good.. but is their any way to create multi-level spinner in android.... i.e. options within options in android
Thank you for your share, helpe me a lot.
Thank you very much, it is simple and very useful!
If someone need, as I did, to select programmatically the value of the spinner, not based on the index or value but based on the ID (from a database for example) you can do this (I am a beginner, not sure is the optimal way but it works):
Suppose you have on your database a table with 2 columns:
ID Language
11 Italian
12 Portuguese
13 Spanish
and you need to select the language from the spinner with ID = 12:
add:
private MyData lista_limbi[] = new MyData[0];
on the declarations of the class
change old values with:
lista_limbi = Arrays.copyOf(lista_limbi, lista_limbi.length + 4);
lista_limbi[0] = new MyData( "","" );
lista_limbi[1] = new MyData( "Italian", "11" );
lista_limbi[2] = new MyData( "Portuguese", "12" );
lista_limbi[3] = new MyData( "Spanish", "13" );
change
if (spinner.getItemAtPosition(i).toString().equalsIgnoreCase(myString))
whith
if (lista_limbi[i].getValue() == myString)
and then from the main program change the selected item:
Spinner mySpinner = (Spinner)findViewById(R.id.spinner_limbi);
mySpinner.setSelection(getIndex(mySpinner, "12"));
=> it will be selected the line with 'Portuguese'
Post a Comment