Maîtriser l'affichage interactif d'images sous Flutter avec Photo View

Le package photo_view est une solution essentielle dans l'écosystème Flutter pour implémenter des visualiseurs d'images réactifs. Il encapsule la complexité de la reconnaissance des gestes (pinch-to-zoom, double-tap, panning) dans un widget déclaratif, idéal pour les galeries photo, les aperçus de produits ou les visualiseurs de documents.

Caractéristiques techniques principales

Le widget PhotoView se distingue par sa capacité à gérer nativement les interactions complexes tout en offrant une API hautement configurable :

  • Interactions gestuelles : Support natif du zoom par pincement, du double-clic et du déplacement par glissement.
  • Contrôle des échelles : Définition précise des limites de zoom (min/max) pour éviter les déformatinos excessives.
  • Transitions Hero : Intégration fluide avec le système de navigation de Flutter pour les animations entre les listes et les détails.
  • Contrôle programmatique : Manipulation de l'état (position, échelle) via un contrôleur dédié.

Intégration et utilisation de base

Ajoutez la dépendance dans votre fichier pubspec.yaml :

dependencies:
  photo_view: ^0.15.0

Exécutez ensuite la commande de synchronisation :

flutter pub get

Voici comment instancier un visualiseur basique avec des contraintes d'échelle personnalisées :

import 'package:photo_view/photo_view.dart';

PhotoView(
  imageProvider: const NetworkImage('https://cdn.exemple.com/assets/panorama.jpg'),
  minScale: PhotoViewComputedScale.contained * 0.5,
  maxScale: PhotoViewComputedScale.covered * 4.0,
  enableRotation: false,
)

Implémentation d'une galerie d'images

Pour afficher des collections multiples avec un balayage horizontal, PhotoViewGallery.builder est l'approche recommandée. Elle optimise la mémoire en ne chargeant que les pages visibles.

PhotoViewGallery.builder(
  itemCount: mediaCollection.length,
  pageController: PageController(),
  builder: (BuildContext context, int pageIndex) {
    final asset = mediaCollection[pageIndex];
    return PhotoViewGalleryPageOptions(
      imageProvider: NetworkImage(asset.remoteUrl),
      initialScale: PhotoViewComputedScale.contained,
      heroAttributes: PhotoViewHeroAttributes(tag: asset.uniqueId),
    );
  },
)

Personnalisations avancées

Manipulation programmatique via le contrôleur

Le PhotoViewController permet de déclencher des zooms ou des déplacements via la logique métier :

final transformCtrl = PhotoViewController();

// Ajustement de l'échelle
transformCtrl.scale = 3.5;

// Déplacement du point de focalisation
transformCtrl.position = const Offset(150.0, -50.0);

Gestion des états de chargement et d'erreur

Il est crucial de fournir un retour visuel lors du chargement d'assets distants volumineux :

PhotoView(
  imageProvider: const NetworkImage('https://api.exemple.com/v1/images/heavy_file.jpg'),
  loadingBuilder: (context, progress) {
    if (progress == null) return const Center(child: Text('Connexion...'));
    final double ratio = progress.cumulativeBytesLoaded / (progress.expectedTotalBytes ?? 1);
    return Center(child: LinearProgressIndicator(value: ratio));
  },
  errorBuilder: (context, error, stack) => const Center(
    child: Icon(Icons.broken_image, color: Colors.redAccent, size: 48),
  ),
)

Résolution de problèmes courants

Perte de qualité lors du zoom

Si l'image devient pixellisée, assurez-vous d'utiliser des assets en haute résolution et d'augmenter la limite supérieure de l'échelle :

PhotoView(
  imageProvider: const AssetImage('assets/ultra_hd_map.jpg'),
  minScale: PhotoViewComputedScale.contained,
  maxScale: PhotoViewComputedScale.covered * 5.0,
)

Conflits de gestes dans les ScrollViews

Lorsque le visualiseur est imbriqué dans une liste défilante, les gestes peuvent entrer en conflit. L'ajustement du comportement du détecteur de gestes résout ce problème :

PhotoView(
  imageProvider: const AssetImage('assets/diagram.jpg'),
  gestureDetectorBehavior: HitTestBehavior.translucent,
)

Étiquettes: Flutter photo-view Dart mobile-development image-gallery

Publié le 5 octobre à 21h59