Android: Jak powiązać spinner z niestandardową listą obiektów?

126

W interfejsie użytkownika musi znajdować się spinner, który zawiera nazwy (nazwy są widoczne), a każda nazwa ma swój własny identyfikator (identyfikatory nie są równe kolejności wyświetlania). Kiedy użytkownik wybierze nazwę z listy, zmienna currentID musi zostać zmieniona.

Aplikacja zawiera ArrayList

Gdzie Użytkownik jest obiektem o identyfikatorze i nazwie:

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

Nie wiem, jak utworzyć pokrętło, które wyświetla listę nazw użytkowników i powiązać elementy pokrętła z identyfikatorami, więc po wybraniu / zmianie elementu pokrętła zmienna currentID jest ustawiana na odpowiednią wartość.

Byłbym wdzięczny, gdyby ktoś mógł pokazać rozwiązanie opisanego problemu lub podać jakikolwiek link przydatny do rozwiązania problemu.

Dzięki!

Niko Gamulin
źródło
Użyj metody setVisibility i ustaw ją na INVISIBLE developer.android.com/reference/android/view/ ...
andoni90

Odpowiedzi:

42

Możesz spojrzeć na tę odpowiedź . Możesz także użyć niestandardowego adaptera, ale poniższe rozwiązanie jest dobre w prostych przypadkach.

Oto ponowna wiadomość:

Więc jeśli przyszedłeś tutaj, ponieważ chcesz mieć zarówno etykiety, jak i wartości w Spinner - oto jak to zrobiłem:

  1. Po prostu stwórz swój Spinnerzwykły sposób
  2. Zdefiniuj w array.xmlpliku 2 tablice o jednakowych rozmiarach - jedną tablicę dla etykiet, jedną tablicę dla wartości
  3. Ustaw swój Spinnerzandroid:entries="@array/labels"
  4. Kiedy potrzebujesz wartości, zrób coś takiego (nie, nie musisz jej łączyć):

      String selectedVal = getResources().getStringArray(R.array.values)[spinner.getSelectedItemPosition()];
Bostone
źródło
2
Czy istnieje elegancki sposób uzyskiwania dostępu do zdefiniowanych etykiet (w celu porównania z selectedVal), aby można było uniknąć zakodowania etykiet ciągów na stałe w kodzie?
Anti Earth
Jest to przypadek powielania danych i należy go unikać.
Binoy Babu
18
Tak źle z punktu widzenia skalowalności - oznacza to, że Twoje „obiekty” nigdy nie mogą być dynamiczne - zła praktyka
Srneczek
1
@Bostone Nie sprawdzałem czasu, ale myślę, że w tym przypadku nie ma to znaczenia. Adaptery istnieją z jakiegoś powodu i założę się, że nie chodzi o zmianę SDK w czasie. To jeden z powodów, dla których stworzyli adaptery na pierwszym miejscu. Możesz więc podać listę złożonych obiektów, więc moim zdaniem zawsze była to zła praktyka nadająca się do użytku tylko w bardzo prostych przypadkach, ale to nie czyni jej dobrą praktyką.
Srneczek
3
@ Bob'sBurgers, nie rozumiesz. Nigdy nie powiedziałem, że to nie działa. Powiedziałem, że to zła praktyka i mam rację. zmienne globalne lub kod w jednym bardzo, bardzo długim pliku też działają, wiesz ... Przy okazji powinieneś komentować stare wątki, ponieważ nadal pojawiają się one w dzisiejszych wyszukiwaniach, a ppl użyje tych (dzisiejszych) błędnych odpowiedzi.
Srneczek
344

Wiem, że wątek jest stary, ale na wszelki wypadek ...

Obiekt użytkownika:

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

Niestandardowy adapter tarczy (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;
    }
}

I implementacja:

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) {  }
        });
    }
}
Joaquin Alberto
źródło
43
To powinna być akceptowana odpowiedź. Tworzenie niestandardowego adaptera jest zdecydowanie najlepszym rozwiązaniem.
jamesc
11
To działało dobrze. Bardzo dobrze. Ale jeden problem. Błystka zmieniła teraz swój styl. Próbuję ustawić nowy xml, aby zmienić dopełnienie, rozmiar tekstu, ale nic się nie dzieje. Sam zmieniam spinner z xml i nadal nic. Jedyną rzeczą, która się zmienia, jest zmiana rozmiaru tekstu TextView z poziomu SpinAdapter. Czy można zachować domyślny styl / motyw pokrętła, ale ładować tego rodzaju wartości?
lantonis,
Zrobiłem to, ale dostaję ogromne opóźnienie. Podczas gdy ja po prostu dodaję 3 razy. Zrobiłem zawyżenie widoku, aby stworzyć mój układ, zawiera tylko ikonę i tekst. Logcat potwierdza mnie, mówiąc Skipped 317 frames! The application may be doing too much work on its main thread.jakieś pomysły?
CularBytes
3
+1 dla tej linii :) User user = adapter.getItem (pozycja);
Ahmad Alkhatib
2
Tylko modyfikacja do ponownego wykorzystania widoku, zamiast tworzyć nowy TextView, powinno to wyglądać tak: TextView label = (TextView) super.getView (position, convertView, parent)
jackcar
93

Najprostsze rozwiązanie

Po przeszukaniu różnych rozwiązań w SO, stwierdziłem, że najprostszym i najczystszym rozwiązaniem do wypełniania Spinnerniestandardowego Objects. Oto pełna realizacja:

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>

W Twojej aktywności

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) {
    }
});
Joshua Pinter
źródło
Jednym małym zastrzeżeniem jest to, że nie ustawia to currentIDnatychmiast po zmianie wartości Spinner . W większości przypadków wartość Spinner jest potrzebna tylko po kolejnym naciśnięciu przycisku, takiego jak Prześlij lub Zapisz , a nie natychmiast po zmianie Spinnera, a jeśli można tego uniknąć, zapewnia to znacznie prostsze rozwiązanie.
Joshua Pinter,
Okazało się, że to działa i po prostu umieszczając ostatnią linię w innym miejscu, możesz obejść "problem" opisany przez @JoshPinter.
x13
@ x13 Zgadza się. Wszystko, co musisz zrobić, aby uzyskać wartość zmiany, to ustawić odbiornik „przy zmianie”, a następnie umieścić w nim getSelectedItem()wywołanie. Dzięki za wskazówkę.
Joshua Pinter
4
Minęły 3 lata i działa niesamowicie! Nie mogę uwierzyć, że ludzie zbytnio komplikują tę prostą rzecz.
Juan De la Cruz
1
@JuanDelaCruz Android i java ułatwiają nadmierną komplikację. Uproszczenie o zwycięstwo!
Joshua Pinter
53

Aby uzyskać proste rozwiązania, możesz po prostu nadpisać „toString” w swoim obiekcie

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

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

a następnie możesz użyć:

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

W ten sposób twój spinner pokaże tylko nazwy użytkowników.

SpyZip
źródło
Jak ustawić spinner na EDYCJA na wybrany element, który wraca po odpowiedzi?
Arnold Brown
9

Zdecydowanie najprostszy sposób, jaki znalazłem:

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

Teraz możesz włożyć dowolny przedmiot do tarczy, a wyświetli on określoną etykietę.

NielW
źródło
8

Wystarczy drobna poprawka do odpowiedzi Joaquina Alberto, aby rozwiązać problem ze stylem. Po prostu zastąp funkcję getDropDownView w niestandardowym adapterze, jak poniżej,

@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;
    }
Tirtharup Bhattacharyya
źródło
1
ta odpowiedź w rzeczywistości nie odpowiada na pytanie, ale wskazuje na kilka ważnych rzeczy związanych z tą odpowiedzią
Sruit A.Suk
6

U mnie działa dobrze, kod potrzebny wokół funkcji getResource () jest następujący:

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
        }

    });

Wystarczy upewnić się (samodzielnie), że wartości w obu tablicach są odpowiednio wyrównane!

Sonja
źródło
5

zainspirowany Joaquinem Alberto, zadziałał dla mnie:

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;
    }
}
Anna Maria
źródło
5

Oparty na przykładzie Joaquina Alberto (dzięki), ale działa dla każdego typu (powinieneś zaimplementować toString () w typie, więc możesz sformatować wynik.

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

Myślę też, że możesz zamienić List na Array, więc nie musisz robić toArray in List, ale mam List ..... :)

Alberto Ricart
źródło
3

Aby zrozumieć sztuczkę, trzeba wiedzieć, jak ogólnie działają Adaptery, a w szczególności ArrayAdapter.

Adaptery: to obiekty, które są w stanie wiązać struktury danych z widżetami, wtedy te widgety wyświetlają te dane na liście lub w Spinnerze.

Tak więc dwa pytania, na które odpowiada Adapter, to:

  1. Który widżet lub widok złożony ma być powiązany ze strukturą danych (obiektem Twojej klasy) dla określonego indeksu?
  2. Jak wyodrębnić dane ze struktury danych (obiektu Twojej klasy) i jak ustawić pola (pola), np EditText. Widżetu lub widoku złożonego na podstawie tych danych?

Odpowiedzi ArrayAdapter to:

  • Każdy widżet (czyli row.xmlOR android.R.layout.simple_spinner_item) dla dowolnego indeksu jest taki sam i jest zawyżany z zasobu, którego identyfikator został przekazany konstruktorowi ArrayAdapter.
  • Każdy widżet powinien być instancją klasy TextView (lub elementu podrzędnego). Metoda widżetu .setText()zostanie użyta z formatem ciągu elementu we wspierającej strukturze danych. Format ciągu zostanie uzyskany przez wywołanie .toString()elementu.

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>

Działa poprawnie, mam nadzieję, że przyda się.

Parag Ghetiya
źródło
2

Mój niestandardowy obiekt to

/**
 * 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;

        }
    }
}

Chciałem również ustawić ten obiekt jako źródło mojego adaptera do mojego spinnera bez rozszerzania ArrayAdapter, aby to, co zrobiłem, było.

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

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

Teraz będziesz mógł zobaczyć wyniki w swojej tarczy, sztuczka polegała na nadpisaniu toString() w swoim niestandardowym obiekcie , więc jakąkolwiek wartość chcesz wyświetlić w przędzarce, po prostu zwróć ją w tej metodzie.

DeltaCap019
źródło
0

Myślę, że najlepszym rozwiązaniem jest „najprostszym rozwiązaniem” przez Josh Pintera .

To zadziałało dla mnie:

//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();
    }

}
lopradi
źródło
0

Jeśli nie potrzebujesz oddzielnej klasy, mam na myśli zwykły adapter zmapowany na twoim obiekcie. Oto mój kod oparty na dostarczonych funkcjach ArrayAdapter.

A ponieważ może być konieczne dodanie elementu po utworzeniu adaptera (np. Asynchroniczne ładowanie elementu bazy danych).

Proste, ale wydajne.

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

A potem możesz użyć tego kodu (nie mogłem umieścić Category [] w konstruktorze adaptera, ponieważ dane są ładowane oddzielnie).

Zauważ, że adapter.addAll (items) odświeża spinner, wywołując notifyDataSetChanged () w wewnętrznym.

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

            @Override
            public void onChanged(@Nullable final List<Category> items) {
                dataAdapter.addAll(items);
            }
});
Zhar
źródło
-1

Robić:

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
            }
        }
Juliano Moraes
źródło
3
Nadal przedłużasz tutaj klasę. Robisz to po prostu z anonimowym przedmiotem.
FutureShocked