Android: Как связать spinner с пользовательским списком объектов?

В пользовательском интерфейсе должен быть счетчик, который содержит некоторые имена (имена видны), и каждое имя имеет свой собственный идентификатор (идентификаторы не равны последовательности отображения). Когда пользователь выбирает имя из списка, переменная currentID должна быть изменена.

Приложение содержит ArrayList

Где Пользователь – это объект с идентификатором и именем:

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

Я не знаю, как создать счетчик, который отображает список имен пользователей и связывает элементы-счетчики с идентификаторами, поэтому, когда выбран элемент-элемент прядильника, переменная currentID устанавливается в соответствующее значение.

Я был бы признателен, если бы кто-нибудь мог показать решение описанной проблемы или предоставить любую ссылку, полезную для решения проблемы.

Благодаря!

Вы можете посмотреть на этот ответ . Вы также можете использовать пользовательский адаптер, но нижеприведенное решение подходит для простых случаев.

Вот повторная публикация:

Поэтому, если вы пришли сюда, потому что хотите, чтобы в Spinner есть как метки, так и значения, вот как я это сделал:

  1. Просто создайте свой Spinner обычным способом
  2. Определите 2 массива равного размера в файле array.xml – один массив для меток, один массив для значений
  3. Установите Spinner с помощью android:entries="@array/labels"
  4. Когда вам нужно значение, сделайте что-нибудь подобное (нет, вам не нужно его связывать):

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

Я знаю, что stream старый, но на всякий случай …

Пользовательский объект:

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

Пользовательский адаптер Spinner (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; } } 

И реализация:

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

Простейшее решение

После очистки различных решений на SO я нашел следующее самое простое и чистое решение для Spinner пользовательскими Objects . Вот полная реализация:

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

разреш / макет / spinner.xml

   

разреш / макет / your_activity_view.xml

     

В вашей деятельности

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

Для простых решений вы можете просто переписать «toString» в свой объект

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

и затем вы можете использовать:

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

Таким образом, ваш счетчик покажет только имена пользователей.

Просто небольшая корректировка ответа Хоакина Альберто может решить проблему стиля. Просто замените функцию getDropDownView в пользовательском адаптере, как показано ниже,

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

Работает отлично для меня, код, необходимый для функции getResource (), выглядит следующим образом:

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

Просто убедитесь, что (по себе) значения в двух массивах правильно выровнены!

вдохновленный Хоакин Альберто, это сработало для меня:

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

На основе примера Joaquin Alberto (спасибо), но он работает для любого типа (вы должны реализовать toString () в типе, чтобы вы могли форматировать вывод.

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

Также я думаю, что вы можете заменить List by Array, поэтому вам не нужно делать toArray в List, но у меня был List ….. 🙂

Самый простой способ, который я нашел:

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

Теперь вы можете вставить любой объект в свой счетчик, и он отобразит указанную метку.

Чтобы понять трюк, нужно знать, как работают адаптеры в целом и ArrayAdapter в частности.

Адаптеры: это объекты, которые могут привязывать структуры данных к виджетам, тогда эти виджеты отображают эти данные в списке или в Spinner.

Таким образом, ответы на два вопроса:

  1. Какой виджет или составной вид необходимо связать с структурой данных (объект classа) для определенного индекса?
  2. Как извлечь данные из структуры данных (объект classа) и как установить поле (ы), т.е. EditText виджета или составного представления в соответствии с этими данными?

Ответы ArrayAdapter:

  • Каждый виджет (т.е. row.xml OR android.R.layout.simple_spinner_item ) для любого индекса один и тот же и раздувается от ресурса, чей идентификатор был предоставлен конструктору ArrayAdapter.
  • Ожидается, что каждый виджет будет экземпляром TextView (или потомок). Метод .setText() виджета будет использоваться со строковым форматом элемента в поддерживающей структуре данных. Формат строки будет получен путем вызова .toString() элемента.

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

     

Он работает правильно, я надеюсь, что это полезно.

Мой пользовательский объект

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

Я также хотел установить этот объект в качестве источника адаптера для моего счетчика, не расширив ArrayAdapter, чтобы я сделал это.

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

Теперь вы сможете увидеть результаты в своем счетчике, трюк состоял в том, чтобы переопределить toString() в вашем пользовательском объекте , поэтому любое значение, которое вы хотите отобразить в spinner, просто возвращает это в этом методе.

Я думаю, что лучшим решением является «Простейшее решение» Джоша Пинтера .

Это сработало для меня:

 //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(); } } 
  • Как добиться анимации пульсации с помощью библиотеки поддержки?
  • Чтобы нарисовать подчеркивание под TextView в Android
  • Совместимость материалов дизайна с версиями ниже Android 5.0?
  • Как запустить приложение при запуске?
  • Давайте будем гением компьютера.