Як користуватися 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) вирішує помилку, невідповідності змінних мною.
— Суміт М Асок

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 адаптер, якщо у вас є два різних адаптери MyClass, вам доведеться робити рефактор. Нарешті, зазвичай погана ідея пов'язати логіку презентації зі своїми моделями. Моделі не повинні знати про те, як вони представлені користувачеві.
— fernandohur

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

Ця відповідь була з 2011 року, і я погоджуюся з @fernandohur - зараз є кращі способи вирішення цього питання.

Я думаю, що це хороша відповідь, тому що в багатьох випадках кожен клас має атрибут, ніж представляє назву об'єкта.
— Jhon Fredy Trujillo Ortega

Це має бути прийнятою відповіддю. Перезапис адаптера лише для прив’язки друкованого імені є поганим кодуванням.
— Л.Грілло

22

Я думаю, що це найкращий підхід. Використання загального класу ArrayAdapter та розширення власного адаптера об'єкта є простим, як описано нижче:

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

Я створив історію з налаштуванням гравітації ArravAdapter, що налаштовує гравітацію TextView:

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


1
Мені дуже сподобався ваш код ЛОТ, але мені знадобилося певний час, щоб зрозуміти, чому він збігався з android.content.res.Resources $ NotFoundException: Ідентифікатор ресурсу # 0x0. У вас є загальний дзвінок адаптера на супер (.., 0, ..), де 0 - це фактично ресурс компонування, якого не існує, тому його потрібно змінити на щось інше .. Також ваш суть 404
— Ev0oD

Врешті-решт я сильно змінився - макет випадаючого меню був іншим, ніж макет показаного пункту, drawText викликався лише на заголовку спінера, а не на його елементах, натиснувши ..
— Ev0oD

Це має бути дійсним як загальний адаптер. Не могли б ви вирішити проблему?
— цезард

Так, я змусив це працювати. Я зрозумів, що ти пропонуєш рішення дещо трохи іншого, ніж те, що я хотів, але я зміг використати твій код як вихідний пункт і внести поправки таким чином, щоб він зробив для мене те, що я хотів. Дякуємо за цей фрагмент коду.
— 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.