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