Implémentation d'une ListView dynamique avec un BaseAdapter personnalisé sur Android

L'utilisation d'un BaseAdapter personnalisé est une approche fondamentale dans le développement Android pour lier dynamiquement des données à une ListView. Contrairement aux adaptateurs simples, un adaptateur personnalisé permet de contrôler entièrement la mise en page de chaque élément et d'intégrer des interacitons complexes, comme la suppression d'un élément directement depuis la liste.

Configuration de l'interface principale et navigation

Le point d'entrée de l'application contient un bouton simple pour naviguer vers l'activité affichant la liste.

layout_home.xml

<?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"
    android:gravity="center"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_open_list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Afficher la liste" />
</LinearLayout>

HomeActivity.java

package com.example.androidui;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class HomeActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_home);
        
        Button btnOpenList = findViewById(R.id.btn_open_list);
        btnOpenList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(HomeActivity.this, UserListActivity.class));
            }
        });
    }
}

Mise en page de la liste et des éléments

L'interface de la liste utilise un conteneur simple, tandis que la mise en page de chaque élément (item_user_row.xml) définit la structure visuelle d'une ligne, incluant une image, des textes et un bouton d'action.

layout_user_list.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/lv_users"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="1dp" />
</FrameLayout>

item_user_row.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp">

    <ImageView
        android:id="@+id/iv_avatar"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginStart="15dp"
        android:layout_toEndOf="@id/iv_avatar"
        android:layout_toStartOf="@id/btn_delete"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/tv_description"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp" />
    </LinearLayout>

    <Button
        android:id="@+id/btn_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:text="Supprimer"
        android:textSize="12sp" />
</RelativeLayout>

Modèle de données et adaptateur personnalisé

Pour optimiser la gestion des données, il est préférable d'utiliser un objet POJO (Plain Old Java Object) plutôt qu'une collection de type Map. L'adaptateur intègre également le pattern ViewHolder pour améliorer les performances de défilement en recyclant les vues.

UserProfile.java

package com.example.androidui;

public class UserProfile {
    private int avatarResId;
    private String name;
    private String description;

    public UserProfile(int avatarResId, String name, String description) {
        this.avatarResId = avatarResId;
        this.name = name;
        this.description = description;
    }

    public int getAvatarResId() { return avatarResId; }
    public String getName() { return name; }
    public String getDescription() { return description; }
}

UserAdapter.java

package com.example.androidui;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class UserAdapter extends BaseAdapter {
    private List<UserProfile> data;
    private Context context;

    public UserAdapter(Context context, List<UserProfile> data) {
        this.context = context;
        this.data = data;
    }

    @Override
    public int getCount() {
        return data != null ? data.size() : 0;
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item_user_row, parent, false);
            holder = new ViewHolder();
            holder.avatar = convertView.findViewById(R.id.iv_avatar);
            holder.name = convertView.findViewById(R.id.tv_name);
            holder.description = convertView.findViewById(R.id.tv_description);
            holder.btnDelete = convertView.findViewById(R.id.btn_delete);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        final UserProfile user = data.get(position);
        holder.avatar.setImageResource(user.getAvatarResId());
        holder.name.setText(user.getName());
        holder.description.setText(user.getDescription());

        holder.btnDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                data.remove(position);
                notifyDataSetChanged();
            }
        });

        return convertView;
    }

    private static class ViewHolder {
        ImageView avatar;
        TextView name;
        TextView description;
        Button btnDelete;
    }
}

Intégration dans l'activité

L'activité principale de la liste initialise le composant ListView, génère un jeu de données simulé et lie l'adaptateur personnalisé pour afficher le contenu.

UserListActivity.java

package com.example.androidui;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

public class UserListActivity extends Activity {
    private ListView lvUsers;
    private UserAdapter adapter;
    private List<UserProfile> userList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_user_list);

        lvUsers = findViewById(R.id.lv_users);
        userList = generateMockData();
        
        adapter = new UserAdapter(this, userList);
        lvUsers.setAdapter(adapter);
    }

    private List<UserProfile> generateMockData() {
        List<UserProfile> list = new ArrayList<>();
        for (int i = 1; i <= 15; i++) {
            list.add(new UserProfile(
                R.mipmap.ic_launcher, 
                "Utilisateur " + i, 
                "Description pour le profil numéro " + i
            ));
        }
        return list;
    }
}

Étiquettes: Android ListView BaseAdapter Java UI

Publié le 11 juillet à 22h26