Android: ¿Cómo enlazar spinner a la lista de objetos personalizados?

En la interfaz de usuario tiene que haber un spinner que contenga algunos nombres (los nombres son visibles) y cada nombre tiene su propia identificación (los ID no son iguales a la secuencia de visualización). Cuando el usuario selecciona el nombre de la lista, la variable ID actual debe modificarse.

La aplicación contiene ArrayList

Donde el usuario es un objeto con ID y nombre:

public class User{ public int ID; public String name; } 

Lo que no sé es cómo crear una rueda giratoria que muestre la lista de nombres de usuario y unir elementos de hiladora a identificadores, de modo que cuando se selecciona / cambia el elemento giratorio, la variable ID actual se establece en el valor apropiado.

Agradecería que alguien pudiera mostrar la solución del problema descrito o proporcionar algún vínculo útil para resolver el problema.

¡Gracias!

Puedes mirar esta respuesta . También puede ir con un adaptador personalizado, pero la solución a continuación está bien para casos simples.

Aquí hay una nueva publicación:

Entonces, si vino aquí porque quiere tener tags y valores en el Spinner, así es como lo hice:

  1. Simplemente crea tu Spinner la manera habitual
  2. Defina 2 matrices de igual tamaño en su archivo array.xml – una matriz para tags, una matriz para valores
  3. Configura tu Spinner con android:entries="@array/labels"
  4. Cuando necesite un valor, haga algo como esto (no, no tiene que encadenarlo):

      String selectedVal = getResources().getStringArray(R.array.values)[spinner.getSelectedItemPosition()]; 

Sé que el hilo es viejo, pero por las dudas …

Objeto de usuario:

 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; } } 

Adaptador de giro personalizado (ArrayAdapter)

 public class SpinAdapter extends ArrayAdapter{ // 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; } } 

Y la implementación:

 public class Main extends Activity { // You spinner view private Spinner mySpinner; // Custom Spinner adapter (ArrayAdapter) // 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) { } }); } } 

La solución más simple

Después de buscar diferentes soluciones en SO, encontré que la siguiente es la solución más simple y limpia para Spinner un Spinner con Objects personalizados. Aquí está la implementación completa:

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

   

res / layout / your_activity_view.xml

     

En tu actividad

 // Gets all users but replace with whatever list of users you want. List users = User.all(); ArrayAdapter userAdapter = new ArrayAdapter(this, R.layout.spinner, users); Spinner userSpinner = (Spinner) findViewById(R.id.user); userSpinner.setAdapter(userAdapter); // And to get the actual User object that was selected, you can do this. User user = (User) ( (Spinner) findViewById(R.id.user) ).getSelectedItem(); 

Para soluciones simples, puede sobrescribir el “toString” en su objeto

 public class User{ public int ID; public String name; @Override public String toString() { return name; } } 

y luego puedes usar:

 ArrayAdapter dataAdapter = new ArrayAdapter(mContext, android.R.layout.simple_spinner_item, listOfUsers); 

De esta forma, su girador mostrará solo los nombres de usuario.

Solo una pequeña modificación a la respuesta de Joaquin Alberto puede resolver el problema del estilo. Solo reemplace la función getDropDownView en el adaptador personalizado como se muestra a continuación,

 @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View v = super.getDropDownView(position, convertView, parent); TextView tv = ((TextView) v); tv.setText(values[position].getName()); tv.setTextColor(Color.BLACK); return v; } 

Funciona bien para mí, el código necesario en torno a getResource () es el siguiente:

 spinner = (Spinner) findViewById(R.id.spinner); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView spinner, View v, int arg2, long arg3) { String selectedVal = getResources().getStringArray(R.array.compass_rate_values)[spinner.getSelectedItemPosition()]; //Do something with the value } @Override public void onNothingSelected(AdapterView arg0) { // TODO Auto-generated method stub } }); 

Solo tiene que asegurarse (solo) de que los valores en las dos matrices estén alineados correctamente.

inspirado por Joaquin Alberto, esto funcionó para mí:

 public class SpinAdapter extends ArrayAdapter{ public SpinAdapter(Context context, int textViewResourceId, User[] values) { super(context, textViewResourceId, values); } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView label = (TextView) super.getView(position, convertView, parent); label.setTextColor(Color.BLACK); label.setText(this.getItem(position).getName()); return label; } @Override public View getDropDownView(int position, View convertView,ViewGroup parent) { TextView label = (TextView) super.getView(position, convertView, parent); label.setTextColor(Color.BLACK); label.setText(this.getItem(position).getName()); return label; } } 

Basado en la muestra de Joaquin Alberto (gracias), pero funciona para cualquier tipo (debe implementar toString () en tipo, para que pueda formatear la salida.

 import java.util.List; import android.content.Context; import android.graphics.Color; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class SpinAdapter extends ArrayAdapter { private Context context; private List values; public SpinAdapter(Context context, int textViewResourceId, List values) { super(context, textViewResourceId, values); this.context = context; this.values = values; } public int getCount() { return values.size(); } public T getItem(int position) { return values.get(position); } public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView label = new TextView(context); label.setTextColor(Color.BLACK); label.setText(values.toArray(new Object[values.size()])[position] .toString()); return label; } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { TextView label = new TextView(context); label.setTextColor(Color.BLACK); label.setText(values.toArray(new Object[values.size()])[position] .toString()); return label; } } 

También creo que puedes reemplazar List by Array para que no necesites hacer Array in List, pero tenía una lista … 🙂

De lejos, la forma más sencilla que he encontrado:

 @Override public String toString() { return this.label; } 

Ahora puede pegar cualquier objeto en su spinner, y mostrará la etiqueta especificada.

Para entender el truco, uno tiene que saber cómo funcionan los adaptadores en general y ArrayAdapter en particular.

Adaptadores: son objetos que pueden unir estructuras de datos a widgets, luego estos widgets muestran esos datos en una Lista o en un Giro.

Entonces las dos preguntas que responde un Adaptador son:

  1. ¿Qué widget o vista compuesta necesita asociarse con una estructura de datos (el objeto de su clase) para un determinado índice?
  2. ¿Cómo extraer los datos de la estructura de datos (el objeto de su clase) y cómo establecer los campos, es decir, EditText del widget o vista compuesta de acuerdo con estos datos?

Las respuestas de ArrayAdapter son:

  • Cada widget (es decir, row.xml OR android.R.layout.simple_spinner_item ) para cualquier índice es el mismo, y está inflado del recurso cuyo ID se le dio al constructor de ArrayAdapter.
  • Se espera que cada widget sea una instancia de TextView (o descendiente). El método .setText() del widget se utilizará con el formato de cadena del elemento en la estructura de datos de soporte. El formato de cadena se obtendrá al invocar .toString() en el elemento.

CustomListViewDemo.java

 public class CustomListViewDemo extends ListActivity { private EfficientAdapter adap; private static String[] data = new String[] { "0", "1", "2", "3", "4" }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); adap = new EfficientAdapter(this); setListAdapter(adap); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub super.onListItemClick(l, v, position, id); Toast.makeText(this, "Click-" + String.valueOf(position), Toast.LENGTH_SHORT).show(); } public static class EfficientAdapter extends BaseAdapter implements Filterable { private LayoutInflater mInflater; private Bitmap mIcon1; private Context context; int firstpos=0; public EfficientAdapter(Context context) { // Cache the LayoutInflate to avoid asking for a new one each time. mInflater = LayoutInflater.from(context); this.context = context; } public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.adaptor_content, null); holder = new ViewHolder(); holder.sp = (Spinner) convertView.findViewById(R.id.spinner1); holder.ArrayAdapter_sp = new ArrayAdapter(parent.getContext(),android.R.layout.simple_spinner_item,data); holder.ArrayAdapter_sp.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); holder.sp.setAdapter( holder.ArrayAdapter_sp); holder.sp.setOnItemSelectedListener(new OnItemSelectedListener() { private int pos = position; @Override public void onItemSelected(AdapterView arg0, View arg1, int p, long arg3) { // TODO Auto-generated method stub Toast.makeText(context, "select spinner " + String.valueOf(pos)+" with value ID "+p, Toast.LENGTH_SHORT).show(); } @Override public void onNothingSelected(AdapterView arg0) { // TODO Auto-generated method stub } }); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } return convertView; } static class ViewHolder { Spinner sp; ArrayAdapter ArrayAdapter_sp; } @Override public Filter getFilter() { // TODO Auto-generated method stub return null; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return 0; } @Override public int getCount() { // TODO Auto-generated method stub return data.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return data[position]; } } } 

adaptor_content.xml

     

main.xml

     

Funciona correctamente, espero que sea útil.

Mi objeto personalizado es

 /** * Created by abhinav-rathore on 08-05-2015. */ public class CategoryTypeResponse { private String message; private int status; private Object[] object; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public Object[] getObject() { return object; } public void setObject(Object[] object) { this.object = object; } @Override public String toString() { return "ClassPojo [message = " + message + ", status = " + status + ", object = " + object + "]"; } public static class Object { private String name; private String _id; private String title; private String desc; private String xhdpi; private String hdpi; private String mdpi; private String hint; private String type; private Brands[] brands; public String getId() { return _id; } public void setId(String id) { this._id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getXhdpi() { return xhdpi; } public void setXhdpi(String xhdpi) { this.xhdpi = xhdpi; } public String getHdpi() { return hdpi; } public void setHdpi(String hdpi) { this.hdpi = hdpi; } public String getMdpi() { return mdpi; } public void setMdpi(String mdpi) { this.mdpi = mdpi; } public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public String getHint() { return hint; } public void setHint(String hint) { this.hint = hint; } public String getType() { return type; } public void setType(String type) { this.type = type; } public Brands[] getBrands() { return brands; } public void setBrands(Brands[] brands) { this.brands = brands; } @Override public String toString() { return "ClassPojo [name = " + name + "]"; } } public static class Brands { private String _id; private String name; private String value; private String categoryid_ref; public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getCategoryid_ref() { return categoryid_ref; } public void setCategoryid_ref(String categoryid_ref) { this.categoryid_ref = categoryid_ref; } @Override public String toString() { return name; } } } 

También quería establecer este objeto como mi fuente de adaptador en mi spinner sin extender ArrayAdapter para que lo que hice fue.

 brandArray = mCategoryTypeResponse.getObject()[fragPosition].getBrands(); ArrayAdapter brandAdapter = new ArrayAdapter< CategoryTypeResponse.Brands>(getActivity(), R.layout.item_spinner, brandArray); 

Ahora podrás ver resultados en tu spinner, el truco fue anular toString() en tu objeto personalizado , así que cualquier valor que quieras mostrar en spinner solo devuelve eso en este método.

Creo que la mejor solución es la “Solución más simple” de Josh Pinter .

Esto funcionó para mí:

 //Code of the activity //get linearLayout LinearLayout linearLayout = (LinearLayout ) view.findViewById(R.id.linearLayoutFragment); LinearLayout linearLayout = new LinearLayout(getActivity()); //display css RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); //create the spinner in a fragment activiy Spinner spn = new Spinner(getActivity()); // create the adapter. ArrayAdapter spinner_adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_item, meta.getValorlistaList()); spinner_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spn.setAdapter(spinner_adapter); //set the default according to value //spn.setSelection(spinnerPosition); linearLayout.addView(spn, params2); 
 //Code of the class ValorLista import java.io.Serializable; import java.util.List; public class ValorLista implements Serializable{ /** * */ private static final long serialVersionUID = 4930195743192929192L; private int id; private String valor; private List metadatoList; public ValorLista() { super(); // TODO Auto-generated constructor stub } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getValor() { return valor; } public void setValor(String valor) { this.valor = valor; } public List getMetadatoList() { return metadatoList; } public void setMetadatoList(List metadatoList) { this.metadatoList = metadatoList; } @Override public String toString() { return getValor(); } }