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

Classe: MyClass

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

Ho creato row.xml nei layout, ma non so come mostrare sia la ragione che il long_val in ListView usando ArrayAdapter.

Risposte:


155

Implementa un adattatore personalizzato per la tua classe:

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

Per coloro che non hanno molta familiarità con il framework Android, questo è spiegato in modo più dettagliato qui: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView .


2
Spiacenti, MyClass item = items.get (position) risolve l'errore, non corrisponde alle variabili da me.
vertice M ha richiesto il

1
Ho rimosso il campo degli articoli dal codice sopra, perché può facilmente portare ad errori - ad esempio se qualcuno cambia l'elenco interno di elementi usando adapter.clear () o adapter.add (...)
prostynick

1
Sono corretto nel supporre che textViewResourceIdnon sia usato sopra?
Gerrytan,

8
da dove viene viewHolder?
Gerry,

2
Che cos'è R.layout.listview_association? È il tuo layout personalizzato? Posso sostituirlo con android.R.layout.simple_list_item_1?
Donato,

76

Puoi semplicemente aggiungere un toString()metodo a MyClass, per http://developer.android.com/reference/android/widget/ArrayAdapter.html :

Tuttavia, viene fatto riferimento a TextView, verrà riempito con toString () di ciascun oggetto nell'array. È possibile aggiungere elenchi o matrici di oggetti personalizzati. Sostituisci il metodo toString () dei tuoi oggetti per determinare quale testo verrà visualizzato per l'elemento nell'elenco.

class MyClass {

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

20
Sebbene la soluzione più semplice, questa (IMHO) non sia una buona idea. Tre motivi: se hai mai bisogno di localizzazione, dovrai refactoring. Funziona solo se si dispone di 1 adattatore, se si dispone di 2 adattatori diversi MyClass, è necessario eseguire il refactoring. Infine, è generalmente una cattiva idea legare la logica di presentazione ai tuoi modelli. I modelli non devono essere consapevoli di come vengono presentati all'utente.
Fernandohur,

2
per rispondere ad alcune delle preoccupazioni di @fernandohur puoi semplicemente creare una classe vista dedicata per ArrayAdapter ... quindi una classe modello di tipo MyClassrichiederebbe di aggiungere una classe dedicata chiamata MyClassViewche avvolge il modello sottostante (e fornisce l' toString( )implementazione
wal

Questa risposta è stata del 2011 e sono d'accordo con @fernandohur - ci sono modi migliori per gestirlo ora.

penso che questa sia una buona risposta perché, in molte volte ogni classe ha un attributo che rappresenta il nome dell'oggetto.
Jhon Fredy Trujillo Ortega,

Questa dovrebbe essere la risposta accettata. Sostituire un adattatore solo per legare il nome stampato è una codifica errata.
L.Grillo,

22

Penso che questo sia l'approccio migliore. L'uso della classe generica ArrayAdapter e l'estensione dell'adattatore per oggetti è semplice come segue:

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

e qui l'adattatore (esempio):

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

}

e infine, come inizializzarlo:

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

Ho creato un Gist con ArrayAdapter personalizzabile con la gravità del layout TextView:

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


1
Mi è piaciuto molto il tuo codice MOLTO, ma mi ci è voluto un po 'di tempo per capire perché stava andando in crash con android.content.res.Resources $ NotFoundException: ID risorsa # 0x0. Nel tuo adattatore generico hai chiamato super (.., 0, ..), dove 0 è in realtà una risorsa di layout, che non esiste, quindi deve essere cambiato in qualcos'altro .. Inoltre, la tua
sintesi

Alla fine ho finito per cambiare molto - il layout del menu a discesa era diverso dal layout dell'elemento mostrato, il disegno era chiamato solo sull'intestazione del filatore, non sui suoi elementi su clic ..
Ev0oD

Questo dovrebbe essere valido come adattatore generico. Potresti risolvere il problema?
Cesare

Sì, l'ho fatto funzionare. Mi sono reso conto che fornisci una soluzione per qualcosa di un po 'diverso da quello che volevo, ma sono stato in grado di utilizzare il tuo codice come punto di partenza e apportare modifiche in modo tale da fare ciò che volevo per me. Grazie per questo pezzo di codice.
Ev0oD

Questo dovrebbe essere fornito di default.
Goddard,

6

Sottoclassare ArrayAdapter e sovrascrivere il metodo getView () per restituire la propria vista che contiene i contenuti che si desidera visualizzare.


5

Ecco un esempio veloce e sporco di come utilizzare un ArrayAdapter se non vuoi disturbarti con l'estensione della classe madre:

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!");
            }
        });
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.