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 conMaterialPageRoute
. 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 afalse
, 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 da0.0
a1.0
durante la transizione.flightDirection
: direzione del volo (HeroFlightDirection.push
oHeroFlightDirection.pop
).fromHeroContext
etoHeroContext
: 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 untag
unico. - Ritorno al punto di origine mantenendo la posizione dell’elemento nella lista originale.
- Implementazione di
HeroMode
per disabilitare temporaneamente l’animazione.