Pages

mardi 21 août 2012

Créer des listes personnalisées en mélangeant image et texte

Les listes proposées par défaut sous Android sont des listes simples permettant d’afficher des occurrences sous la forme de texte. Nous allons voir comment mettre en place une vue un peu plus complexe comme l’exemple ci-dessous



Les éléments de la liste sont affichés dans un layout de type ListView. Nous allons commencer par écrire deux fichiers layout pour décrire le ListView et décrire comment une occurrence de notre liste doit s’afficher.

Dans l’application Feuille de match nous souhaitons par exemple afficher la liste des feuilles déjà créées en mettant en avant une image schématisant le sport lié, la date de la rencontre et le score des deux équipes.

Définition des layout
openeritem.xml contient la description du layout affichant une ligne dans notre liste. Nous utilisons dans notre cas un RelativeLayout. Ce layout permet de placer des champs les uns en fonctions des aytre en déclarant des contraintes du type layout_toRightOf, layout_toLeftOf, layout_above, layout_below, layout_center_vertical….

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
    <ImageView
            android:id="@+id/photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingRight="15dp"
            android:paddingTop="10dp"
            android:contentDescription="@string/match_sport"/>
 
     <TextView android:id="@+id/name"
            android:textSize="18sp"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/photo"/>
      
     <TextView android:id="@+id/score"
            android:textSize="14sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/photo"
            android:layout_below="@+id/name"/>
</RelativeLayout>


openerlist.xml décrit une ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>
</LinearLayout>


Définition d’un Adapter
Pour pouvoir peupler et gérer l’affichage d’une ListView l’API Android propose des classes Adapater et notamment la classe BaseAdapter qui peut servir de classe de base à la fois pour une ListView ou un Spinner. Nous allons donc créer notre propre classe Adapter.
public class ListViewImageScoreSheetAdapter extends BaseAdapter {
    private List<ScoreSheet> items;
    private Context context;
   
    public ListViewImageScoreSheetAdapter(Context context, List<ScoreSheet> results) {
      this.items = results;
      this.context=context;
    }
   
    public int getCount() {
      return items.size();
    }

    public Object getItem(int position) {
      return items.get(position);
    }

    public long getItemId(int position) {
      return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
      ViewHolder holder;
      if (convertView == null) {
          convertView = LayoutInflater.from(context).inflate(R.layout.openeritem, null);
          holder = new ViewHolder();
          holder.itemDate = (TextView) convertView.findViewById(R.id.name);
          holder.itemScore = (TextView) convertView.findViewById(R.id.score);
          holder.itemImage = (ImageView) convertView.findViewById(R.id.photo);
         
          convertView.setTag(holder);
      } else {
          holder = (ViewHolder) convertView.getTag();
      }
      ScoreSheet scoreSheet = items.get(position);
     
      holder.itemDate.setText(scoreSheet.getDate());
      holder.itemImage.setImageResource(context.getResources().getIdentifier(
            "sport"+scoreSheet.getSport().getId().intValue(),
            "drawable",
            context.getPackageName()));

      String scoreMatch = new StringBuilder()
            .append(context.getText(R.string.team_local))
            .append(" : ")
            .append(scoreSheet.getScoreHome())
            .append(" ")
            .append(context.getText(R.string.team_visitor))
            .append(" : ")
            .append(scoreSheet.getScoreVisitor())
            .append(" ")
            .toString();
      holder.itemScore.setText(scoreMatch);
      return convertView;
    }

    static class ViewHolder {
      TextView itemDate;
      TextView itemScore;
      ImageView itemImage;
    }

}

Activity pour gérer la liste view 
Pour finir le code dans l’activité pour gérer cette liste est le suivant. Lors de la création de l’activité on raccroche notre liste et nous rajoutons la gestion du clic sur un des éléments. La liste est elle affichée dans la méthode onResume car l’activité peut être mise en pause ou masquée et pas forcément reconstruite lors de son accès.

public class ScoreSheetOpener extends SherlockActivity {
    public static final String TAG = "ScoreSheetOpener";
    private ListView listView;
    private ScoreSheetService scoreSheetService;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.openerlist);
      listView = (ListView) findViewById(R.id.list);

      // Ajout aussi d'un event sur la liste pour les modifs des temps forts
      listView.setClickable(true);
      listView.setOnItemClickListener(new OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Toast.makeText(view.getContext(),
                  "Clic sur elt " + ((ScoreSheet) listView.getItemAtPosition(position)).getId(),
                  Toast.LENGTH_SHORT).show();
          }
      });
    }

    @Override
    protected void onResume() {
      super.onResume();
      List<ScoreSheet> scoreSheets=null;
      // TODO ==> recuperation de la liste des elements

      ListViewImageScoreSheetAdapter adapter = new ListViewImageScoreSheetAdapter(this, scoreSheets);
      listView.setAdapter(adapter);
    }

}


Aucun commentaire:

Enregistrer un commentaire

Remarque : Seul un membre de ce blog est autorisé à enregistrer un commentaire.