import 'package:flutter/material.dart'; /// Envuelve un item de lista para que entre con fade+slide sutil la primera /// vez que se monta, en vez de aparecer de golpe. `index` da un pequeño /// retraso creciente (tope en 8) para que una tanda de items nuevos (carga /// inicial, resultado de busqueda, pagina nueva) se sienta como cascada en /// vez de parpadeo simultaneo. No repite la animacion en rebuilds del mismo /// item ya montado (usar una key estable por item, ej. su id, para que /// Flutter no lo trate como "nuevo" en cada build). class FadeInEntry extends StatefulWidget { const FadeInEntry({ super.key, required this.child, this.index = 0, }); final Widget child; final int index; @override State createState() => _FadeInEntryState(); } class _FadeInEntryState extends State { bool _visible = false; @override void initState() { super.initState(); final delayMs = widget.index.clamp(0, 8) * 40; Future.delayed(Duration(milliseconds: delayMs), () { if (mounted) setState(() => _visible = true); }); } @override Widget build(BuildContext context) { return AnimatedOpacity( opacity: _visible ? 1 : 0, duration: const Duration(milliseconds: 250), curve: Curves.easeOut, child: AnimatedSlide( offset: _visible ? Offset.zero : const Offset(0, 0.04), duration: const Duration(milliseconds: 250), curve: Curves.easeOut, child: widget.child, ), ); } }