Android: How to bind spinner to custom object list?
I know the thread is old, but just in case...
User object:
public class User{
private int _id;
private String _name;
public User(){
this._id = 0;
this._name = "";
}
public void setId(int id){
this._id = id;
}
public int getId(){
return this._id;
}
public void setName(String name){
this._name = name;
}
public String getName(){
return this._name;
}
}
Custom Spinner Adapter (ArrayAdapter)
public class SpinAdapter extends ArrayAdapter<User>{
// Your sent context
private Context context;
// Your custom values for the spinner (User)
private User[] values;
public SpinAdapter(Context context, int textViewResourceId,
User[] values) {
super(context, textViewResourceId, values);
this.context = context;
this.values = values;
}
@Override
public int getCount(){
return values.length;
}
@Override
public User getItem(int position){
return values[position];
}
@Override
public long getItemId(int position){
return position;
}
// And the "magic" goes here
// This is for the "passive" state of the spinner
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// I created a dynamic TextView here, but you can reference your own custom layout for each spinner item
TextView label = (TextView) super.getView(position, convertView, parent);
label.setTextColor(Color.BLACK);
// Then you can get the current item using the values array (Users array) and the current position
// You can NOW reference each method you has created in your bean object (User class)
label.setText(values[position].getName());
// And finally return your dynamic (or custom) view for each spinner item
return label;
}
// And here is when the "chooser" is popped up
// Normally is the same view, but you can customize it if you want
@Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
TextView label = (TextView) super.getDropDownView(position, convertView, parent);
label.setTextColor(Color.BLACK);
label.setText(values[position].getName());
return label;
}
}
And the implementarion:
public class Main extends Activity {
// You spinner view
private Spinner mySpinner;
// Custom Spinner adapter (ArrayAdapter<User>)
// You can define as a private to use it in the all class
// This is the object that is going to do the "magic"
private SpinAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create the Users array
// You can get this retrieving from an external source
User[] users = new User[2];
users[0] = new User();
users[0].setId(1);
users[0].setName("Joaquin");
users[1] = new User();
users[1].setId(2);
users[1].setName("Alberto");
// Initialize the adapter sending the current context
// Send the simple_spinner_item layout
// And finally send the Users array (Your data)
adapter = new SpinAdapter(Main.this,
android.R.layout.simple_spinner_item,
users);
mySpinner = (Spinner) findViewById(R.id.miSpinner);
mySpinner.setAdapter(adapter); // Set the custom adapter to the spinner
// You can create an anonymous listener to handle the event when is selected an spinner item
mySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view,
int position, long id) {
// Here you get the current item (a User object) that is selected by its position
User user = adapter.getItem(position);
// Here you can do the action you want to...
Toast.makeText(Main.this, "ID: " + user.getId() + "\nName: " + user.getName(),
Toast.LENGTH_SHORT).show();
}
@Override
public void onNothingSelected(AdapterView<?> adapter) { }
});
}
}
You can look at this answer. You can also go with a custom adapter, but the solution below is fine for simple cases.
Here's a re-post:
So if you came here because you want to have both labels and values in the Spinner - here's how I did it:
- Just create your
Spinner
the usual way - Define 2 equal size arrays in your
array.xml
file -- one array for labels, one array for values - Set your
Spinner
withandroid:entries="@array/labels"
When you need a value, do something like this (no, you don't have to chain it):
String selectedVal = getResources().getStringArray(R.array.values)[spinner.getSelectedItemPosition()];
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:
User.java
public class User{
public int ID;
public String name;
@Override
public String toString() {
return this.name; // 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/user" />
</LinearLayout>
In Your Activity
List<User> users = User.all(); // This example assumes you're getting all Users but adjust it for your Class and needs.
ArrayAdapter userAdapter = new ArrayAdapter(this, R.layout.spinner, users);
Spinner userSpinner = (Spinner) findViewById(R.id.user);
userSpinner.setAdapter(userAdapter);
userSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Get the value selected by the user
// e.g. to store it as a field or immediately call a method
User user = (User) parent.getSelectedItem();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
For simple solutions you can just Overwrite the "toString" in your object
public class User{
public int ID;
public String name;
@Override
public String toString() {
return name;
}
}
and then you can use:
ArrayAdapter<User> dataAdapter = new ArrayAdapter<User>(mContext, android.R.layout.simple_spinner_item, listOfUsers);
This way your spinner will show only the user names.