perf: ajout de ListView itemExtent/prototypeItem pour l'optimisation des performances

This commit is contained in:
ElPoyo
2026-05-26 13:43:18 +02:00
parent 0bbc77ffc8
commit 4284142b1e
2 changed files with 79 additions and 65 deletions
+74 -62
View File
@@ -601,80 +601,92 @@ class _CalendarPageState extends State<CalendarPage> {
constraints: BoxConstraints(
maxHeight: isMobile ? 240 : 280,
),
child: ListView.separated(
child: ListView.builder(
shrinkWrap: true,
itemCount: _searchResults.length,
physics: const ClampingScrollPhysics(),
separatorBuilder: (context, index) =>
const SizedBox(height: 8),
// ✅ prototypeItem : les résultats ont une hauteur variable
// selon la présence du champ adresse (~56px sans, ~70px avec).
// prototypeItem à 72px (cas avec adresse + padding) pour
// que Flutter estime correctement la hauteur scrollable.
// ListView.separated ne supporte pas itemExtent/prototypeItem,
// d'où la conversion en ListView.builder avec séparateur intégré.
prototypeItem: const SizedBox(height: 72),
itemBuilder: (context, index) {
final event = _searchResults[index];
final isSelected = _selectedEvent?.id == event.id;
final isLast = index == _searchResults.length - 1;
return Material(
color: isSelected
? AppColors.rouge.withOpacity(0.08)
: Colors.white,
borderRadius: BorderRadius.circular(12),
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () => _onSearchResultSelected(event),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: _getStatusColor(event.status),
shape: BoxShape.circle,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
event.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.w600,
),
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Material(
color: isSelected
? AppColors.rouge.withOpacity(0.08)
: Colors.white,
borderRadius: BorderRadius.circular(12),
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () => _onSearchResultSelected(event),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: _getStatusColor(event.status),
shape: BoxShape.circle,
),
const SizedBox(height: 4),
Text(
_formatSearchResultDate(
event.startDateTime),
style: TextStyle(
color: Colors.grey.shade700,
fontSize: 12,
),
),
if (event.address.isNotEmpty) ...[
const SizedBox(height: 2),
Text(
event.address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 12,
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
event.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.w600,
),
),
),
],
],
),
const SizedBox(height: 4),
Text(
_formatSearchResultDate(
event.startDateTime),
style: TextStyle(
color: Colors.grey.shade700,
fontSize: 12,
),
),
if (event.address.isNotEmpty) ...[
const SizedBox(height: 2),
Text(
event.address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.grey.shade600,
fontSize: 12,
),
),
],
],
),
),
const SizedBox(width: 8),
const Icon(Icons.chevron_right,
color: Colors.grey),
],
),
const SizedBox(width: 8),
const Icon(Icons.chevron_right,
color: Colors.grey),
],
),
),
),
),
if (!isLast) const SizedBox(height: 8),
],
);
},
),
@@ -501,9 +501,11 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
return ListView.builder(
controller: _scrollController,
itemCount: itemCount,
// ✅ Ajouter une estimation de la hauteur pour améliorer le scroll
// Note : À ajuster selon la hauteur réelle de vos cartes
// itemExtent: 140, // Décommentez si toutes les cartes ont la même hauteur
// ✅ prototypeItem utilisé car les cartes ont des hauteurs variables :
// - Les équipements standards (ListTile + margin) font ~88px
// - Les consommables/câbles affichent _buildQuantityDisplay en plus (~30px)
// - prototypeItem permet à Flutter d'optimiser le scroll sans couper les items
prototypeItem: const SizedBox(height: 88),
// ✅ Augmenter le cache pour un scroll plus fluide
cacheExtent: 500, // Précharger 500px en plus
itemBuilder: (context, index) {