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
tagdeve 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
Herofunziona solo conMaterialPageRoute. Con animazioni personalizzate (PageRouteBuilder), va gestito manualmente.
Limiti e Considerazioni su Hero
Heroutilizza un GlobalKey internamente per gestire le animazioni.- Non è consigliato utilizzarlo per liste estese o widget complessi con molti elementi condivisi.
- Il
tagdeve 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 afalse, disabilita l’animazione Hero.- Il
Heroresta 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 da0.0a1.0durante la transizione.flightDirection: direzione del volo (HeroFlightDirection.pushoHeroFlightDirection.pop).fromHeroContextetoHeroContext: 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
Herocon untagunico. - Ritorno al punto di origine mantenendo la posizione dell’elemento nella lista originale.
- Implementazione di
HeroModeper disabilitare temporaneamente l’animazione.