Costruire la ParallaxCard con l'effetto di traslazione
Ora creiamo il widget ParallaxCard. Ascoltiamo lo scroll tramite AnimatedBuilder collegato allo ScrollController: ogni volta che il controller cambia, ricostruiamo solo la parte necessaria.
Usiamo un ClipRRect per arrotondare gli angoli e posizioniamo l'immagine con OverflowBox, così da avere spazio extra per traslarla senza mostrare bordi vuoti. La traslazione verticale è calcolata dal fattore ottenuto nel passo precedente.
class ParallaxCard extends StatelessWidget {
final ParallaxItem item;
final ScrollController scrollController;
ParallaxCard({
super.key,
required this.item,
required this.scrollController,
});
final GlobalKey _cardKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Padding(
key: _cardKey,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: SizedBox(
height: 220,
child: Stack(
fit: StackFit.expand,
children: [
AnimatedBuilder(
animation: scrollController,
builder: (context, _) {
final factor =
_calculateParallaxFactor(_cardKey, scrollController);
// massimo spostamento in pixel
final double dy = (factor - 0.5) * 80;
return OverflowBox(
maxHeight: 300,
child: Transform.translate(
offset: Offset(0, dy),
child: Image.network(
item.imageUrl,
fit: BoxFit.cover,
),
),
);
},
),
_buildGradientOverlay(),
_buildTexts(),
],
),
),
),
);
}
Widget _buildGradientOverlay() {
return DecoratedBox(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.transparent, Colors.black54],
),
),
);
}
Widget _buildTexts() {
return Positioned(
left: 16,
bottom: 16,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.title,
style: const TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
Text(
item.subtitle,
style: const TextStyle(color: Colors.white70, fontSize: 14),
),
],
),
);
}
}
Risultato atteso
Scorrendo la lista, le immagini si muovono più lentamente rispetto alle card creando l'effetto parallax.