Android: Wie binde ich den Spinner an eine benutzerdefinierte Objektliste?
Lesezeit: 8 Minuten
In der Benutzeroberfläche muss es einen Spinner geben, der einige Namen enthält (die Namen sind sichtbar) und jeder Name hat seine eigene ID (die IDs sind nicht gleich der Anzeigereihenfolge). Wenn der Benutzer den Namen aus der Liste auswählt, muss die Variable currentID geändert werden.
Die Anwendung enthält die ArrayList
Wobei User ein Objekt mit ID und Name ist:
public class User{
public int ID;
public String name;
}
Was ich nicht weiß, ist, wie man einen Spinner erstellt, der die Liste der Benutzernamen anzeigt und Spinner-Elemente an IDs bindet, sodass bei Auswahl/Änderung des Spinner-Elements die Variable currentID auf den entsprechenden Wert gesetzt wird.
Ich würde mich freuen, wenn jemand die Lösung des beschriebenen Problems zeigen oder einen Link bereitstellen könnte, der zur Lösung des Problems nützlich ist.
Danke!
Joaquín Alberto
Ich weiß, der Thread ist alt, aber nur für den Fall…
Benutzerobjekt:
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;
}
}
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;
}
}
Und die Umsetzung:
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) { }
});
}
}
Dies sollte die akzeptierte Antwort sein. Das Erstellen eines benutzerdefinierten Adapters ist definitiv der richtige Weg.
– Jamesc
27. Januar 2013 um 12:50 Uhr
Dies funktionierte gut. Sehr schön. Aber ein Problem. Der Spinner änderte nun seinen Stil. Ich versuche, eine neue XML-Datei festzulegen, um die Auffüllungen und die Textgröße zu ändern, aber es passiert nichts. Ich ändere den Spinner selbst aus dem XML und stil nichts. Das einzige, was sich ändert, ist, wenn ich die Textgröße der TextView innerhalb des SpinAdapters ändere. Gibt es eine Möglichkeit, den Standard-Spinner-Stil/das Standardthema beizubehalten, aber diese Art von Werten zu laden?
– Lantonis
16. April 2014 um 8:51 Uhr
Ich habe dies getan, aber ich bekomme eine enorme Verzögerung. Während ich nur 3 mal addiere. Ich habe eine Ansicht aufgeblasen, um mein Layout zu erstellen, sie enthält nur ein Symbol und Text. Der Logcat bestätigt mir das mit den Worten Skipped 317 frames! The application may be doing too much work on its main thread. Irgendwelche Ideen?
– CularBytes
20. Mai 2015 um 19:02 Uhr
+1 für diese Zeile 🙂 User user = adapter.getItem(position);
– Ahmad Alkhatib
30. September 2015 um 10:06 Uhr
Nur eine Änderung, um die Ansicht wiederzuverwenden, anstatt eine neue TextView zu erstellen, sollte sie so aussehen: TextView label = (TextView) super.getView(position, convertView, parent)
– Wagenheber
5. Mai 2017 um 13:25 Uhr
Josua Pinter
Einfachste Lösung
Nachdem ich verschiedene Lösungen auf SO durchforstet hatte, fand ich die folgende als die einfachste und sauberste Lösung zum Bevölkern von a Spinner mit Brauch Objects. Hier ist die vollständige Implementierung:
Benutzer.java
public class User{
public int ID;
public String name;
@Override
public String toString() {
return this.name; // What to display in the Spinner list.
}
}
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) {
}
});
Eine kleine Einschränkung ist, dass dies nicht festgelegt wird currentID sobald Spinner Wert ändert. Meistens benötigen Sie nur den Wert der Spinner nach dem anschließenden Drücken einer Taste, wie z einreichen oder Speichernnicht unmittelbar nach dem Spinner Änderungen und wenn es vermieden werden kann, bietet dies eine viel einfachere Lösung.
– Joshua Pinter
16. Januar 2014 um 18:06 Uhr
Ich habe festgestellt, dass dies funktioniert, und indem Sie einfach die letzte Zeile an einer anderen Stelle einfügen, können Sie das von @JoshPinter beschriebene “Problem” umgehen.
– x13
16. September 2016 um 7:08 Uhr
@x13 Das ist richtig. Alles, was Sie tun müssen, um den Wert bei Änderung zu erhalten, ist, einen “on change”-Listener einzurichten und dann die getSelectedItem() ruf das an. Danke für den Tipp.
– Joshua Pinter
18. Mai 2017 um 20:55 Uhr
3 Jahre sind vergangen und funktioniert erstaunlich! Ich kann nicht glauben, dass die Leute diese einfache Sache zu kompliziert machen.
– Juan de la Cruz
17. Dezember 2017 um 4:43 Uhr
@JuanDelaCruz Android und Java machen es einfach, Dinge zu verkomplizieren. Vereinfachung für den Sieg!
– Joshua Pinter
18. Dezember 2017 um 2:33 Uhr
Für einfache Lösungen können Sie einfach den “toString” in Ihrem Objekt überschreiben
public class User{
public int ID;
public String name;
@Override
public String toString() {
return name;
}
}
und dann können Sie verwenden:
ArrayAdapter<User> dataAdapter = new ArrayAdapter<User>(mContext, android.R.layout.simple_spinner_item, listOfUsers);
Auf diese Weise zeigt Ihr Spinner nur die Benutzernamen an.
Wie stelle ich den Spinner auf BEARBEITEN auf das ausgewählte Element ein, das bei der Antwort zurückkehrt?
– Arnold Braun
1. Juni 2018 um 4:57 Uhr
Boston
Sie können sich diese Antwort ansehen. Sie können auch einen benutzerdefinierten Adapter verwenden, aber die folgende Lösung ist für einfache Fälle in Ordnung.
Hier ein Repost:
Wenn Sie also hierher gekommen sind, weil Sie sowohl Labels als auch Werte im Spinner haben möchten, habe ich es so gemacht:
Erstellen Sie einfach Ihre Spinner der übliche Weg
Definieren Sie 2 gleich große Arrays in Ihrer array.xml file — ein Array für Labels, ein Array für Werte
Setze deine Spinner mit android:entries="@array/labels"
Wenn Sie einen Wert benötigen, machen Sie so etwas (nein, Sie müssen ihn nicht verketten):
Bei weitem der einfachste Weg, den ich gefunden habe:
@Override
public String toString() {
return this.label;
}
Jetzt können Sie ein beliebiges Objekt in Ihren Spinner stecken, und es wird das angegebene Etikett angezeigt.
Savad KP
Nur eine kleine Änderung an Joaquin Albertos Antwort kann das Stilproblem lösen. Ersetzen Sie einfach die getDropDownView-Funktion im benutzerdefinierten Adapter wie unten,
@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;
}
Sonja
Funktioniert gut für mich, der Code, der für die Sache getResource () benötigt wird, lautet wie folgt:
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
}
});
Sie müssen nur (selbst) sicherstellen, dass die Werte in den beiden Arrays richtig ausgerichtet sind!
9160400cookie-checkAndroid: Wie binde ich den Spinner an eine benutzerdefinierte Objektliste?yes