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

J'ai créé row.xml dans des mises en page, mais je ne sais pas comment afficher à la fois la raison et le long_val dans le ListView à l'aide d'ArrayAdapter.

Sumit M Asok
la source

Réponses:

155

Implémentez un adaptateur personnalisé pour votre 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;
    }
}

Pour ceux qui ne sont pas très familiers avec le framework Android, cela est expliqué plus en détail ici: https://github.com/codepath/android_guides/wiki/Using-an-ArrayAdapter-with-ListView .

Nikola Smiljanić
la source
2
Désolé, MyClass item = items.get (position) résout l'erreur, ne correspond pas aux variables par moi.
Sumit M Asok
1
J'ai supprimé le champ des éléments du code ci-dessus, car cela peut facilement entraîner des erreurs - par exemple si quelqu'un modifie la liste interne des éléments à l'aide de adapter.clear () ou adapter.add (...)
prostynick
1
Ai-je raison de supposer que ce textViewResourceIdn'est pas utilisé ci-dessus?
gerrytan
8
d'où vient viewHolder?
Gerry
2
Qu'est-ce que R.layout.listview_association? Est-ce votre mise en page personnalisée? Puis-je le remplacer par android.R.layout.simple_list_item_1?
Donato
76

Vous pouvez simplement ajouter une toString()méthode à MyClass, par http://developer.android.com/reference/android/widget/ArrayAdapter.html :

Cependant, le TextView est référencé, il sera rempli avec le toString () de chaque objet du tableau. Vous pouvez ajouter des listes ou des tableaux d'objets personnalisés. Remplacez la méthode toString () de vos objets pour déterminer le texte qui sera affiché pour l'élément dans la liste.

class MyClass {

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

la source
20
Bien que la solution la plus simple, ce n'est (à mon humble avis) pas une très bonne idée. Trois raisons: si jamais vous avez besoin d'une localisation, vous devrez refactoriser. Cela ne fonctionne que si vous avez 1 adaptateur, si vous avez 2 adaptateurs différents pour MyClass, vous devrez refactoriser. Enfin, c'est généralement une mauvaise idée de lier la logique de présentation à vos modèles. Les modèles ne doivent pas savoir comment ils sont présentés à l'utilisateur.
fernandohur
2
pour résoudre certaines des préoccupations de @fernandohur, vous pouvez simplement créer une classe de vue dédiée pour le ArrayAdapter ... donc une classe de modèle de type MyClassvous obligerait à ajouter une classe dédiée appelée MyClassViewqui encapsule le modèle sous-jacent (et fournit l' toString( )implémentation
wal
Cette réponse remonte à 2011, et je suis d'accord avec @fernandohur - il existe de meilleures façons de gérer cela maintenant.
Je pense que c'est une bonne réponse car, dans bien des cas, chaque classe a un attribut qui représente le nom de l'objet.
Jhon Fredy Trujillo Ortega
Cela devrait être la réponse acceptée. Remplacer un adaptateur uniquement pour lier le nom imprimé est un mauvais codage.
L.Grillo
22

Je pense que c'est la meilleure approche. L'utilisation de la classe ArrayAdapter générique et étend votre propre adaptateur d'objet est aussi simple que suit:

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

et voici votre adaptateur (exemple):

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

}

et enfin, comment l'initialiser:

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

J'ai créé un ArrayAdapter personnalisable Gist avec la mise en page TextView gravity:

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

cesards
la source
1
J'ai beaucoup aimé votre code, mais il m'a fallu un certain temps pour comprendre pourquoi il plantait avec android.content.res.Resources $ NotFoundException: Resource ID # 0x0. Vous avez dans votre adaptateur générique un appel sur super (.., 0, ..), où 0 est en fait une ressource de mise en page, qui n'existe pas, donc elle doit être remplacée par autre chose. De plus, votre
essence
En fin de compte, j'ai fini par beaucoup changer - la disposition du menu déroulant était différente de la disposition de l'élément affiché, le drawText n'était appelé que sur l'en-tête du spinner, pas sur ses éléments sur cliqué ..
Ev0oD
Cela doit être valide en tant qu'adaptateur générique. Pouvez-vous résoudre le problème?
cesards
Ouais, je l'ai fait fonctionner. J'ai réalisé que vous apportiez une solution pour quelque chose d'un peu différent de ce que je voulais, mais j'ai pu utiliser votre code comme point de départ et apporter des modifications d'une manière qui a fait pour moi ce que je voulais. Merci pour ce morceau de code.
Ev0oD
Cela devrait être fourni par défaut.
Goddard
6

Sous- classez ArrayAdapter et remplacez la méthode getView () pour renvoyer votre propre vue qui contient le contenu que vous souhaitez afficher.

Klarth
la source
5

Voici un exemple rapide et sale de la façon d'utiliser un ArrayAdapter si vous ne voulez pas vous soucier d'étendre la classe mère:

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!");
            }
        });
    }
}
François Dermu
la source