Skip to Content
FlutterLezione 4 Navigazione4.3 Hero animazione di transizione tra schermate

Hero: animazione di transizione tra schermate

Il widget Hero consente di creare transizioni animate tra due schermate per un widget condiviso, come un’immagine, un avatar o un testo. È particolarmente utile per mantenere un contesto visivo durante la navigazione, creando un’esperienza utente più fluida e intuitiva.

Quando un widget con lo stesso tag appare su due route diverse, Flutter crea un’animazione fluida tra le due versioni durante la navigazione con Navigator. Questo rende possibile animare un elemento da una schermata all’altra mantenendo la continuità visiva.

Hero( tag: 'fotoProfilo', child: Image.asset('assets/avatar.png', width: 100), )

Nota: Il tag deve essere identico nelle due schermate per far funzionare l’animazione. È case-sensitive e deve essere univoco all’interno dell’albero dei widget.


Quando usarlo?

  • Per migliorare l’esperienza utente durante il passaggio da una lista a un dettaglio
  • Per transizioni eleganti su immagini, avatar, titoli, card
  • Per evidenziare contenuti specifici mantenendo il contesto visivo tra le schermate
  • Per semplificare la comprensione della navigazione da parte dell’utente

Hero funziona solo con MaterialPageRoute. Con animazioni personalizzate (PageRouteBuilder), va gestito manualmente.


Limiti e Considerazioni su Hero

  • Hero utilizza un GlobalKey internamente per gestire le animazioni.
  • Non è consigliato utilizzarlo per liste estese o widget complessi con molti elementi condivisi.
  • Il tag deve essere univoco all’interno dell’intera struttura dei widget. Un tag duplicato causerà errori di runtime.
  • Hero può animare solo widget che hanno una dimensione fissa o calcolabile.

Hero con PageRouteBuilder

Se utilizzi PageRouteBuilder, Hero non gestisce automaticamente l’animazione. È necessario specificare l’animazione manualmente:

Navigator.push( context, PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => SecondPage(), transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation, child: child, ); }, ), );

HeroMode: Controllare l’Animazione Hero

HeroMode è un widget che consente di abilitare o disabilitare temporaneamente le animazioni Hero per un sottoalbero di widget. Questo è particolarmente utile in scenari in cui:

  • Si desidera mantenere un Hero visibile ma senza eseguire la transizione animata.
  • Si vuole disabilitare temporaneamente un Hero per evitare conflitti di animazione con altri hero con lo stesso tag.

Sintassi Base di HeroMode

HeroMode( enabled: false, child: Hero( tag: 'avatar', child: Image.asset('assets/avatar.png', width: 100), ), )
  • enabled: se impostato a false, disabilita l’animazione Hero.
  • Il Hero resta visibile, ma la transizione animata non avverrà.

Hero FlightShuttleBuilder: Personalizzare le Animazioni Hero

HeroFlightShuttleBuilder è un parametro del widget Hero che consente di personalizzare l’animazione di transizione tra due schermate. Questo parametro è utilizzato per definire il widget che volerà da una schermata all’altra, consentendo di applicare trasformazioni avanzate come rotazioni, scalature o effetti visivi personalizzati.


Sintassi Base di flightShuttleBuilder

Hero( tag: 'image', flightShuttleBuilder: ( flightContext, animation, flightDirection, fromHeroContext, toHeroContext) { return ScaleTransition( scale: animation, child: toHeroContext.widget, ); }, child: Image.asset('assets/image.png'), )
  • flightContext: contesto del volo.
  • animation: animazione che va da 0.0 a 1.0 durante la transizione.
  • flightDirection: direzione del volo (HeroFlightDirection.push o HeroFlightDirection.pop).
  • fromHeroContext e toHeroContext: contesti del widget di partenza e di arrivo.

Esempio Avanzato: Rotazione durante il volo

In questo esempio, applichiamo una rotazione durante il volo utilizzando un RotationTransition:

Hero( tag: 'avatar', flightShuttleBuilder: (flightContext, animation, flightDirection, fromHeroContext, toHeroContext) { return RotationTransition( turns: animation, child: toHeroContext.widget, ); }, child: ClipOval( child: Image.network('https://picsum.photos/200'), ), )
  • Durante il volo, l’immagine ruoterà a 360 gradi.

Altre Transizioni

1. FadeTransition

Hero( tag: 'item', flightShuttleBuilder: (flightContext, animation, flightDirection, fromHeroContext, toHeroContext) { return FadeTransition( opacity: animation, child: toHeroContext.widget, ); }, child: Image.network('https://picsum.photos/100'), )

2. SlideTransition

Hero( tag: 'slide', flightShuttleBuilder: (flightContext, animation, flightDirection, fromHeroContext, toHeroContext) { return SlideTransition( position: Tween<Offset>( begin: Offset(1, 0), end: Offset(0, 0), ).animate(animation), child: toHeroContext.widget, ); }, child: Image.network('https://picsum.photos/100'), )

3. Scale & Rotation Transition

Combinare più transizioni:

Hero( tag: 'combined', flightShuttleBuilder: (flightContext, animation, flightDirection, fromHeroContext, toHeroContext) { return ScaleTransition( scale: animation, child: RotationTransition( turns: animation, child: toHeroContext.widget, ), ); }, child: Image.network('https://picsum.photos/200'), )

Esercizio - Implementazione di Hero Avanzato

Obiettivo:

Implementare una transizione fluida tra una schermata di lista (HomeScreen) e una schermata di dettaglio (DetailScreen) utilizzando il widget Hero per animare un’immagine condivisa. Includere:

  • Animazione scalata personalizzata con HeroFlightShuttleBuilder.
  • Gestione di liste dinamiche, dove ogni elemento ha un Hero con un tag unico.
  • Ritorno al punto di origine mantenendo la posizione dell’elemento nella lista originale.
  • Implementazione di HeroMode per disabilitare temporaneamente l’animazione.