Як користуватися 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.