Как использовать 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.