Заполните ArrayList представлениями при использовании объекта Spinner

Я много работаю с ListViews и ExpandableListViews в Android. И я знаю, как заполнить списки изображениями и текстом, создав один customAdaper - и класс адаптера, расширяющий, например, Arrayadapter.

В этом приложении, которое я сейчас разрабатываю, я использую Spinner вместе с ArrayAdapter. В подклассе ArrayAdapter я переопределяю метод getView для заполнения представлений текстом и изображениями.

Но проблема в том, что getView вызывается только один раз - для первого элемента списка, отображаемого при запуске приложения и при выборе элемента из списка. Вот вроде работает. Но когда я расширяю список по списку, метод getView НЕ вызывается - в список помещаются только имена из строки

String[] string = {"солнце", "венера", "земля", "марш"};

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

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

В классе, который расширяет Activity

 Spinner spinner = (Spinner) findViewById(R.id.planets_spinner);

 String[] string = {"sun", "venus", "earth", "march"};
 MyArrayAdapter adapter = new MyArrayAdapter(this, string);
 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 spinner.setAdapter(adapter);

И пользовательский адаптер

public class MyArrayAdapter extends ArrayAdapter <String> {

   private final String[] values;
   private final Context context;

   public MyArrayAdapter(Context context, String[] values) {
      super (context, R.layout.celestial_list, values);
      this.values = values;
      this.context = context;
   }

   private static class ViewHolder {
       TextView textView;
       ImageView imageView;
       ImageView infoView;
   }

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {


       View view = null;
       ViewHolder viewHolder;

       if (convertView == null) {
       LayoutInflater inflater = (LayoutInflater)  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.celestial_list, parent, false);
        viewHolder = new ViewHolder();
        viewHolder.textView = (TextView) view.findViewById(R.id.label);
        viewHolder.imageView = (ImageView) view.findViewById(R.id.icon);
        view.setTag(viewHolder);
       } else {
           view = convertView;
           viewHolder = (ViewHolder) view.getTag();
       }

       System.out.println("view = " + view + " för position " + position);
       viewHolder.textView.setText(values[position]);

            switch (position) {
       case 0:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 1:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 2:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       case 3:
           viewHolder.imageView.setImageResource(R.drawable.sun);
           break;
       }


       return view;
 }

}

Скриншот 1. Вроде нормально - getView вызывается...

введите здесь описание изображения

Скриншот 2, но только для выбранного объекта списка - не для остальных. Здесь используется только String[]

введите здесь описание изображения


person user3155478    schedule 03.08.2014    source источник


Ответы (2)


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

по http://developer.android.com/guide/topics/ui/controls/spinner.html , вы должны

  • убедитесь, что ваш класс Activity implements OnItemSelectedListener ,
  • добавь onItemSelected и если нужно onNothingSelected поставь свой
  • вход в код селектора изображения внутри onItemSelected (не забудьте использовать parent.getItemAtPosition(pos) для получения текущей позиции).
person Antoine Baqain    schedule 03.08.2014

Адаптеры Spinner работают немного иначе:

Вы должны добавить:

public class MyArrayAdapter  extends BaseAdapter implements SpinnerAdapter {

@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        convertView = newDropDownView(parent);
    }

    bindDropDownView(position, convertView);
    return convertView;

}

protected View newDropDownView(ViewGroup parent) { ... }

protected void bindDropDownView(int position, View view) { ... }


@Override
public View getView(int position, View convertView, ViewGroup parent) { ... }


}

Таким образом, getView() будет вызываться для текущего выбранного элемента, который виден, когда счетчик не развернут. В то время как getDropDownView() будет вызываться для каждого элемента в списке счетчика. Так это то, что вы ищете.

Кстати. вот несколько полезных классов адаптеров (использует кинжал для внедрения зависимостей, но вы можете просто скопировать код и стереть класс Injector): https://github.com/sockeqwe/appkit/tree/master/adapter/src/main/java/com/hannesdorfmann/appkit/adapter

person sockeqwe    schedule 03.08.2014
comment
хорошо, спасибо, но я получаю IllegalStateException: ArrayAdapter требует, чтобы идентификатор ресурса был textView. Вероятно, именно здесь я делаю супер-вызов конструктору базового класса, где передается идентификатор ресурса. Прохожу весь макет. Все в порядке, пока я использую метод getView. Но теперь, когда я использую метод getDropDownView, я получаю это исключение и вылетаю. Вопрос в том, как я могу получить textview там? Должен ли я раздувать xml-файл, как я это делаю в getView? - person user3155478; 03.08.2014
comment
Используйте BaseAdapter вместо ArrayAdapter, затем в newDropDownView() вам нужно раздуть свой XML-макет (настроить ViewHolder и т.д.)... - person sockeqwe; 03.08.2014
comment
Я перешел на BaseAdapter, но теперь проблема в том, что getView и getDropDownView не вызываются. И я больше не могу использовать setDropDownViewResource(); - person user3155478; 03.08.2014