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

Kelas: MyClass

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

Saya telah membuat row.xml dalam tata letak, tetapi tidak tahu cara menampilkan alasan dan long_val di ListView menggunakan ArrayAdapter.

Sumit M Asok
sumber

Jawaban:

155

Terapkan adaptor khusus untuk kelas Anda:

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

Bagi mereka yang tidak terbiasa dengan kerangka kerja Android, ini dijelaskan secara lebih rinci di sini: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView .

Nikola Smiljanić
sumber
2
Maaf, item MyClass = items.get (posisi) menyelesaikan kesalahan, ketidakcocokan variabel oleh saya.
Sumit M Asok
1
Saya telah menghapus bidang item dari kode di atas, karena dapat dengan mudah menyebabkan kesalahan - misalnya jika seseorang mengubah daftar internal item menggunakan adapter.clear () atau adapter.add (...)
prostynick
1
Apakah saya benar dengan asumsi textViewResourceIdtidak digunakan di atas?
gerrytan
8
dari mana viewHolder berasal?
Gerry
2
Apa itu R.layout.listview_association? Apakah itu tata letak khusus Anda? Bisakah saya menggantinya dengan android.R.layout.simple_list_item_1?
Donato
76

Anda bisa menambahkan toString()metode ke MyClass, per http://developer.android.com/reference/android/widget/ArrayAdapter.html :

Namun TextView direferensikan, itu akan diisi dengan toString () dari setiap objek dalam array. Anda dapat menambahkan daftar atau array objek khusus. Ganti metode toString () objek Anda untuk menentukan teks apa yang akan ditampilkan untuk item dalam daftar.

class MyClass {

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

sumber
20
Meskipun solusi paling sederhana, ini (IMHO) bukan ide yang sangat bagus. Tiga alasan: Jika Anda memerlukan pelokalan, Anda harus melakukan refactor. Ini hanya berfungsi jika Anda memiliki 1 adaptor, jika Anda memiliki 2 adapter berbeda untuk MyClass, Anda harus refactor. Akhirnya, umumnya ide yang buruk untuk mengikat logika presentasi ke model Anda. Model seharusnya tidak menyadari bagaimana mereka disajikan kepada pengguna.
fernandohur
2
untuk mengatasi beberapa masalah @fernandohur Anda cukup membuat kelas tampilan khusus untuk ArrayAdapter ... sehingga model kelas tipe MyClassakan meminta Anda untuk menambahkan kelas khusus yang disebut MyClassViewyang membungkus model yang mendasarinya (dan menyediakan toString( )implementasi
wal
Jawaban ini berasal dari 2011, dan saya setuju dengan @fernandohur - ada cara yang lebih baik untuk menangani ini sekarang.
Saya pikir ini adalah jawaban yang baik karena, dalam banyak kali setiap kelas memiliki atribut daripada mewakili nama objek.
Jhon Fredy Trujillo Ortega
Ini harus menjadi jawaban yang diterima. Mengganti adaptor hanya untuk mengikat nama yang dicetak adalah pengkodean yang buruk.
L.Grillo
22

Saya pikir ini adalah pendekatan terbaik. Menggunakan kelas ArrayAdapter generik dan memperluas adaptor Object Anda sendiri sesederhana berikut:

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

dan di sini adaptor Anda (contoh):

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

}

dan akhirnya, bagaimana menginisialisasi:

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

Saya telah membuat intisari dengan tata letak gravitasi TextView yang dapat disesuaikan ArrayAdapter:

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

cesards
sumber
1
Saya benar-benar menyukai kode Anda BANYAK, tetapi perlu beberapa saat untuk mencari tahu, mengapa kode ini mogok dengan android.content.res.Resources $ NotFoundException: Resource ID # 0x0. Anda memiliki panggilan adaptor generik pada super (.., 0, ..), di mana 0 sebenarnya adalah sumber daya tata letak, yang tidak ada, sehingga harus diubah menjadi sesuatu yang lain .. Juga, intisari Anda adalah 404
Ev0oD
Pada akhirnya saya akhirnya banyak berubah - tata letak menu dropdown berbeda dari tata letak item yang ditampilkan, drawText hanya dipanggil pada header pemintal, bukan pada itemnya pada klik ..
Ev0oD
Ini harus valid sebagai adaptor generik. Bisakah Anda memecahkan masalah?
cesards
Ya, saya membuatnya bekerja. Saya menyadari bahwa Anda memberikan solusi untuk sesuatu yang sedikit berbeda dari yang saya inginkan, tetapi saya dapat menggunakan kode Anda sebagai titik awal dan membuat perubahan dengan cara yang dilakukan untuk saya apa yang saya inginkan. Terima kasih atas kode ini.
Ev0oD
Ini harus disediakan secara default.
Goddard
6

Subkelas ArrayAdapter dan ganti metode getView () untuk mengembalikan tampilan Anda sendiri yang berisi konten yang ingin Anda tampilkan.

Klarth
sumber
5

Berikut adalah contoh cepat dan kotor tentang cara menggunakan ArrayAdapter jika Anda tidak ingin repot-repot memperpanjang kelas induk:

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!");
            }
        });
    }
}
Francois Dermu
sumber