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


126

En la interfaz de usuario tiene que haber una ruleta que contenga algunos nombres (los nombres son visibles) y cada nombre tiene su propia identificación (las identificaciones no son iguales a la secuencia de visualización). Cuando el usuario selecciona el nombre de la lista, se debe cambiar la variable currentID.

La aplicación contiene la ArrayList

Donde 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 ruleta que muestre la lista de nombres de usuarios y vincular los elementos de la ruleta a las ID, de modo que cuando el elemento de la ruleta se selecciona / cambia, la variable currentID se establece en el valor apropiado.

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

¡Gracias!


Utilice el método setVisibility y configúrelo como INVISIBLE developer.android.com/reference/android/view/…
andoni90 el

Respuestas:


42

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

Aquí hay una nueva publicación:

Entonces, si viniste aquí porque quieres tener etiquetas y valores en el Spinner, así es como lo hice:

  1. Solo crea tu Spinnerforma habitual
  2. Defina 2 matrices de igual tamaño en su array.xmlarchivo: una matriz para etiquetas, una matriz para valores
  3. Configura tu Spinnerconandroid: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()];

2
¿Existe una manera elegante de acceder a las etiquetas definidas (para comparar con selectedVal), de modo que se pueda evitar codificar las etiquetas de cadena en el código?
Anti Tierra

Este es un caso de duplicación de datos y debe evitarse.
Binoy Babu

18
Tan equivocado desde el punto de vista de la escalabilidad: significa que sus "objetos" nunca pueden ser dinámicos - mala práctica
Srneczek

1
@Bostone No verifiqué la hora, pero creo que es irrelevante en este caso. Los adaptadores están ahí por alguna razón y apuesto a que no se trata de un cambio en el SDK a tiempo. Es una de las razones por las que crearon adaptadores en primer lugar. Por lo tanto, puede servir una lista de objetos complejos, por lo que, en mi opinión, esto siempre fue una mala práctica, solo se podía usar en casos muy simples, pero eso no la convierte en una buena práctica.
Srneczek

3
@ Bob'sBurgers te estás perdiendo el punto. Nunca dije que no funciona. Dije que es una mala práctica y estoy en lo cierto. las variables globales o el código en 1 archivo muy, muy largo también están funcionando, ya sabes ... Por cierto, deberías comentar los hilos viejos porque todavía aparecen en las búsquedas de hoy y ppl usará esas (hoy) respuestas incorrectas.
Srneczek

344

Sé que el hilo es viejo, pero por si acaso ...

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 giratorio personalizado (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;
    }
}

Y la implementación:

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

43
Esta debería ser la respuesta aceptada. Crear un adaptador personalizado es definitivamente el camino a seguir.
jamesc

11
Esto funcionó bien. Muy agradable. Pero un problema. La ruleta ahora cambió su estilo. Intento establecer un nuevo xml para cambiar los rellenos, el tamaño del texto, pero no sucede nada. Yo mismo cambio la ruleta del xml y todavía no. Lo único que cambia es si cambio el tamaño del texto de TextView desde el SpinAdapter. ¿Hay alguna forma de mantener el estilo / tema de ruleta predeterminado pero cargar este tipo de valores?
lantonis

He hecho esto, pero estoy teniendo una gran cantidad de retraso. Si bien solo agrego 3 veces. Inflé una vista para hacer mi diseño, solo contiene un icono y texto. El logcat me confirma diciendo ¿ Skipped 317 frames! The application may be doing too much work on its main thread.Alguna idea?
CularBytes

3
+1 para esta línea :) Usuario usuario = adapter.getItem (posición);
Ahmad Alkhatib

2
Solo una modificación para reutilizar la vista, en lugar de crear un nuevo TextView, debería hacer lo siguiente: TextView label = (TextView) super.getView (position, convertView, parent)
jackcar

93

La solución más simple

Después de buscar diferentes soluciones en SO, descubrí que la siguiente es la solución más simple y limpia para completar una aplicación Spinnerpersonalizada Objects. 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

<?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>

En su actividad

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

Una pequeña advertencia es que esto no establece el currentIDtan pronto como cambia el valor de Spinner . La mayoría de las veces solo necesita el valor del Spinner después de presionar posteriormente un botón, como Enviar o Guardar , no inmediatamente después de que el Spinner cambie y, si se puede evitar, esto proporciona una solución mucho más simple.
Joshua Pinter

Encontré que esto funciona, y simplemente colocando la última línea en otro lugar, puede evitar el "problema" descrito por @JoshPinter.
x13

@ x13 Eso es correcto. Todo lo que necesita hacer para obtener el valor en el cambio es configurar un escucha "en cambio" y luego poner la getSelectedItem()llamada en eso. Gracias por el consejo.
Joshua Pinter

44
¡Han pasado 3 años y funciona de maravilla! No puedo creer que la gente complique demasiado esta cosa simple.
Juan De la Cruz

1
@JuanDelaCruz Android y Java facilitan la complicación excesiva de las cosas. Simplificación para la victoria!
Joshua Pinter

53

Para soluciones simples, simplemente 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<User> dataAdapter = new ArrayAdapter<User>(mContext, android.R.layout.simple_spinner_item, listOfUsers);

De esta manera, su ruleta mostrará solo los nombres de usuario.


¿Cómo configurar la ruleta en EDITAR al elemento seleccionado que devuelve en respuesta?
Arnold Brown,

9

Con mucho, la forma más simple que he encontrado:

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

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


8

Solo un pequeño ajuste a la respuesta de Joaquín Alberto puede resolver el problema de estilo. Simplemente 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;
    }

1
esta respuesta en realidad no responde la pregunta, pero señala algunas cosas importantes relacionadas con esta respuesta
Sruit A.Suk

6

Funciona bien para mí, el código necesario alrededor de 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 necesita asegurarse (por sí mismo) de que los valores en las dos matrices estén alineados correctamente!


5

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

public class SpinAdapter extends ArrayAdapter<User>{


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

5

Basado en el ejemplo de Joaquín 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<T> extends ArrayAdapter<T> {
private Context context;
private List<T> values;

public SpinAdapter(Context context, int textViewResourceId, List<T> 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 puede reemplazar List by Array, por lo que no necesita hacer toArray in List, pero tenía una List ..... :)


3

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 Spinner.

Entonces las dos preguntas que responde un Adaptador son:

  1. ¿Qué widget o vista compuesta debe 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, EditTextdel widget o la vista compuesta de acuerdo con estos datos?

Las respuestas de ArrayAdapter son:

  • Cada widget (es decir, row.xmlOR android.R.layout.simple_spinner_item) para cualquier índice es el mismo, y se infla desde el recurso cuya ID se le dio al constructor de ArrayAdapter.
  • Se espera que cada widget sea una instancia de TextView (o descendiente). El .setText()método del widget se utilizará con el formato de cadena del elemento en la estructura de datos de soporte. El formato de cadena se obtendrá invocando .toString()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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/lineItem"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical" >

    <Spinner
        android:id="@+id/spinner1"
        android:layout_width="314dp"
        android:layout_height="wrap_content" />

</LinearLayout>

main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent" android:layout_width="fill_parent"
    >

    <ListView
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginBottom="60dip"
        android:layout_marginTop="10dip"
        android:cacheColorHint="#00000000"
        android:drawSelectorOnTop="false" />

</RelativeLayout>

Funciona correctamente, espero que sea útil.


2

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 fuente de mi adaptador para mi spinner sin extender ArrayAdapter para que lo que hice fuera.

brandArray = mCategoryTypeResponse.getObject()[fragPosition].getBrands();

ArrayAdapter brandAdapter = new ArrayAdapter< CategoryTypeResponse.Brands>(getActivity(),
                R.layout.item_spinner, brandArray);

Ahora podrá ver los resultados en su ruleta, el truco consistía en anular toString() su objeto personalizado , por lo que cualquier valor que desee mostrar en la ruleta simplemente devuelva eso en este método.


0

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<ValorLista> spinner_adapter = new ArrayAdapter<ValorLista>(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<Metadato> 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<Metadato> getMetadatoList() {
        return metadatoList;
    }
    public void setMetadatoList(List<Metadato> metadatoList) {
        this.metadatoList = metadatoList;
    }

    @Override
    public String toString() {  
        return getValor();
    }

}

0

Si no necesita una clase separada, me refiero a un simple adaptador asignado a su objeto. Aquí está mi código basado en las funciones ArrayAdapter proporcionadas.

Y porque es posible que deba agregar un elemento después de la creación del adaptador (por ejemplo, carga asincrónica del elemento de la base de datos).

Simple pero eficiente.

editCategorySpinner = view.findViewById(R.id.discovery_edit_category_spinner);

// Drop down layout style - list view with radio button         
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

// attaching data adapter to spinner, as you can see i have no data at this moment
editCategorySpinner.setAdapter(dataAdapter);
final ArrayAdapter<Category> dataAdapter = new ArrayAdapter<Category>

(getActivity(), android.R.layout.simple_spinner_item, new ArrayList<Category>(0)) {


        // 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)
            Category item = getItem(position);
            label.setText(item.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);
            Category item = getItem(position);
            label.setText(item.getName());

            return label;
        }
    };

Y luego puede usar este código (no pude poner Categoría [] en el constructor del adaptador porque los datos se cargan por separado).

Tenga en cuenta que adapter.addAll (items) actualiza el spinner llamando a notifyDataSetChanged () en interno.

categoryRepository.getAll().observe(this, new Observer<List<Category>>() {

            @Override
            public void onChanged(@Nullable final List<Category> items) {
                dataAdapter.addAll(items);
            }
});

-1

Hacer:

spinner.adapter = object: ArrayAdapter<Project>(
            container.context,
            android.R.layout.simple_spinner_dropdown_item,
            state.projects
        ) {
            override fun getDropDownView(
                position: Int,
                convertView: View?,
                parent: ViewGroup
            ): View {
                val label = super.getView(position, convertView, parent) as TextView
                label.text = getItem(position)?.title
                return label
            }

            override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
                val label = super.getView(position, convertView, parent) as TextView
                label.text = getItem(position)?.title
                return label
            }
        }

3
Todavía estás extendiendo una clase aquí. Solo lo estás haciendo con un objeto anónimo.
FutureShocked
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.