Как использовать ArrayAdapter <myClass>


129
ArrayList<MyClass> myList = new ArrayList<MyClass>();

ListView listView = (ListView) findViewById(R.id.list);

ArrayAdapter<MyClass> adapter = new ArrayAdapter<MyClass>(this, R.layout.row,
    to, myList.);
listView.setAdapter(adapter);

Класс: MyClass

class MyClass {
    public String reason;
    public long long_val;
}

Я создал row.xml в макетах, но не знаю, как показать причину и long_val в ListView с помощью ArrayAdapter.

Ответы:


155

Реализуйте собственный адаптер для вашего класса:

public class MyClassAdapter extends ArrayAdapter<MyClass> {

    private static class ViewHolder {
        private TextView itemView;
    }

    public MyClassAdapter(Context context, int textViewResourceId, ArrayList<MyClass> items) {
        super(context, textViewResourceId, items);
    }

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

        if (convertView == null) {
            convertView = LayoutInflater.from(this.getContext())
            .inflate(R.layout.listview_association, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.itemView = (TextView) convertView.findViewById(R.id.ItemView);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        MyClass item = getItem(position);
        if (item!= null) {
            // My layout has only one TextView
                // do whatever you want with your string and long
            viewHolder.itemView.setText(String.format("%s %d", item.reason, item.long_val));
        }

        return convertView;
    }
}

Для тех, кто не очень знаком с платформой Android, это более подробно объясняется здесь: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView .


2
Извините, MyClass item = items.get (position) решает ошибку, не соответствует моим переменным.
Sumit M Asok

1
Я удалил поле элементов из приведенного выше кода, потому что это может легко привести к ошибкам - например, если кто-то изменит внутренний список элементов с помощью adapter.clear () или adapter.add (...)
prostynick

1
Правильно ли я предполагаю, textViewResourceIdчто выше не используется?
gerrytan

8
откуда появился viewHolder?
Джерри

2
Что такое R.layout.listview_association? Это ваш индивидуальный макет? Можно заменить на android.R.layout.simple_list_item_1?
Донато

76

Вы можете просто добавить toString()метод в MyClass для http://developer.android.com/reference/android/widget/ArrayAdapter.html :

Несмотря на то, что имеется ссылка на TextView, он будет заполнен функцией toString () каждого объекта в массиве. Вы можете добавлять списки или массивы настраиваемых объектов. Переопределите метод toString () ваших объектов, чтобы определить, какой текст будет отображаться для элемента в списке.

class MyClass {

 @Override
 public String toString() {
  return "Hello, world.";
 }
}

20
Хотя самое простое решение, это (ИМХО) не очень хорошая идея. Три причины: если вам когда-нибудь понадобится локализация, вам придется провести рефакторинг. Это работает, только если у вас 1 адаптер. Если у вас 2 разных адаптера MyClass, вам придется провести рефакторинг. Наконец, как правило, привязывать логику представления к вашим моделям - плохая идея. Модели не должны знать, как они представлены пользователю.
fernandohur

2
для решения некоторых проблем @fernandohur вы можете просто создать выделенный класс представления для ArrayAdapter ... поэтому для класса модели типа MyClassпотребуется добавить выделенный класс, MyClassViewкоторый обертывает базовую модель (и обеспечивает toString( )реализацию
wal

Этот ответ был получен в 2011 году, и я согласен с @fernandohur - сейчас есть лучшие способы справиться с этим.

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

Это должен быть принятый ответ. Переопределение адаптера только для привязки напечатанного имени - плохая кодировка.
L.Grillo

22

Думаю, это лучший подход. Использование универсального класса ArrayAdapter и расширение вашего собственного адаптера Object очень просто:

public abstract class GenericArrayAdapter<T> extends ArrayAdapter<T> {

  // Vars
  private LayoutInflater mInflater;

  public GenericArrayAdapter(Context context, ArrayList<T> objects) {
    super(context, 0, objects);
    init(context);
  }

  // Headers
  public abstract void drawText(TextView textView, T object);

  private void init(Context context) {
    this.mInflater = LayoutInflater.from(context);
  }

  @Override public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder vh;
    if (convertView == null) {
      convertView = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
      vh = new ViewHolder(convertView);
      convertView.setTag(vh);
    } else {
      vh = (ViewHolder) convertView.getTag();
    }

    drawText(vh.textView, getItem(position));

    return convertView;
  }

  static class ViewHolder {

    TextView textView;

    private ViewHolder(View rootView) {
      textView = (TextView) rootView.findViewById(android.R.id.text1);
    }
  }
}

а вот и ваш адаптер (пример):

public class SizeArrayAdapter extends GenericArrayAdapter<Size> {

  public SizeArrayAdapter(Context context, ArrayList<Size> objects) {
    super(context, objects);
  }

  @Override public void drawText(TextView textView, Size object) {
    textView.setText(object.getName());
  }

}

и, наконец, как его инициализировать:

ArrayList<Size> sizes = getArguments().getParcelableArrayList(Constants.ARG_PRODUCT_SIZES);
SizeArrayAdapter sizeArrayAdapter = new SizeArrayAdapter(getActivity(), sizes);
listView.setAdapter(sizeArrayAdapter);

Я создал Gist с настраиваемой гравитацией макета TextView ArrayAdapter:

https://gist.github.com/m3n0R/8822803


1
Мне действительно очень понравился ваш код, но мне потребовалось время, чтобы понять, почему он дает сбой с android.content.res.Resources $ NotFoundException: Resource ID # 0x0. В вашем универсальном адаптере есть вызов super (.., 0, ..), где 0 на самом деле является ресурсом макета, который не существует, поэтому его нужно изменить на что-то еще .. Кроме того, ваша суть 404
Ev0oD

В конце концов, мне пришлось многое изменить - макет выпадающего меню отличался от макета показанного элемента, drawText вызывался только в заголовке счетчика, а не в его элементах при нажатии ..
Ev0oD

Это должен быть универсальный адаптер. Не могли бы вы решить проблему?
cesards

Да, я заставил это работать. Я понял, что вы предлагаете решение для чего-то немного отличного от того, что я хотел, но я смог использовать ваш код в качестве отправной точки и внести поправки таким образом, чтобы он сделал для меня то, что я хотел. Спасибо за этот фрагмент кода.
Ev0oD

Это должно быть предусмотрено по умолчанию.
Годдард

6

Создайте подкласс ArrayAdapter и переопределите метод getView (), чтобы вернуть собственное представление, содержащее содержимое, которое вы хотите отобразить.


5

Вот быстрый и грязный пример того, как использовать ArrayAdapter, если вы не хотите беспокоиться о расширении материнского класса:

class MyClass extends Activity {
    private ArrayAdapter<String> mAdapter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        mAdapter = new ArrayAdapter<String>(getApplicationContext(),
            android.R.layout.simple_dropdown_item_1line, android.R.id.text1);

        final ListView list = (ListView) findViewById(R.id.list);
        list.setAdapter(mAdapter);

        //Add Some Items in your list:
        for (int i = 1; i <= 10; i++) {
            mAdapter.add("Item " + i);
        }

        // And if you want selection feedback:
        list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                //Do whatever you want with the selected item
                Log.d(TAG, mAdapter.getItem(position) + " has been selected!");
            }
        });
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.