Rive y Lottie en FlutterFlow: widgets y límites
Por el equipo de Charmotion · Actualizado el

FlutterFlow tiene un widget RiveAnimation integrado que reproduce un .riv desde un asset o una URL, con selectores de artboard y de animación, y una acción Rive Animation para iniciar la reproducción. Su documentación no cubre los inputs de la máquina de estados (state machine) ni Data Binding, así que para cambiar el estado de ánimo de un personaje o disparar reacciones necesitas un widget personalizado basado en el paquete rive de Flutter.
Puntos clave
- El widget RiveAnimation integrado reproduce timelines; el control de la máquina de estados no está documentado.
- Un widget personalizado con el paquete
riveexpone un parámetromoody triggers. - El widget LottieAnimation de FlutterFlow cubre clips lineales con acciones de inicio y pausa.
- Inicializa el runtime de Rive una sola vez al arrancar, antes de cargar cualquier archivo.
- Prueba los widgets personalizados en un build real; las vistas previas pueden no renderizar el código personalizado igual.
¿FlutterFlow es compatible con Rive de forma nativa?
Sí, para la reproducción. El widget RiveAnimation de FlutterFlow está en Base Elements, en el panel de widgets. Eliges una fuente (un asset subido o una URL de red), seleccionas un artboard en un menú desplegable, eliges las animaciones que se reproducirán y dejas Auto Animate activado para que la reproducción empiece automáticamente. Una acción Rive Animation aparte puede iniciar la reproducción desde un botón o un evento de página.
| Necesidad | RiveAnimation integrado | Widget personalizado |
|---|---|---|
| Reproducir un timeline o ponerlo en loop | Yes | Yes |
| Definir un número de la máquina de estados, disparar un trigger | No documentado | Yes |
| View model de Data Binding | No documentado | Yes |
| Sin código | Yes | No |
Por eso el widget integrado funciona bien para una ilustración en loop o una intro puntual. Una mascota de marca que debe verse pensativa mientras se ejecuta una consulta y celebrar cuando sale bien necesita que el estado de la app controle su máquina de estados, y ahí es donde entra el widget personalizado.
¿Cómo agrego un .riv como asset o como fuente de red?
Con el widget integrado:
- Arrastra RiveAnimation desde Base Elements a la página.
- En el panel de propiedades, define la fuente como Asset y sube el .riv, o como Network y pega una URL HTTPS.
- Elige el artboard y las animaciones que se reproducirán.
- Deja Auto Animate activado para los loops, o desactívalo e inicia la reproducción con la acción Rive Animation.
- Dale al widget un ancho y un alto fijos para que el diseño no salte mientras carga el archivo.
Los assets van dentro de la app y funcionan sin conexión. Los archivos de red reducen el peso del binario y se pueden actualizar sin volver a publicar, pero necesitan conexión en la primera carga. Para un personaje que aparece al iniciar la app o en el onboarding, es mejor usar un asset.
Lo mismo aplica a un widget personalizado: los assets subidos quedan en el paquete de assets de la app y se pueden cargar por ruta, y los archivos de red se pueden cargar por URL.
¿El widget integrado puede controlar los inputs de la máquina de estados?
No, según la documentación de FlutterFlow. La página de RiveAnimation describe la fuente, el artboard, la selección de animaciones y Auto Animate, además de la acción que inicia la reproducción. No menciona máquinas de estados, inputs ni view models. Los hilos de la comunidad que preguntan cómo controlar una máquina de estados llegan a la misma conclusión y usan un widget personalizado.
La consecuencia práctica: un archivo construido en torno a una máquina de estados solo reproduce su estado predeterminado en el widget integrado, o nada útil si depende de inputs para elegir un loop. Elegir timelines por nombre puede funcionar con archivos simples, pero pierdes las transiciones que creó el diseñador y tienes que secuenciar la reproducción tú mismo.

Los archivos de Charmotion muestran la diferencia con claridad. Cada set es un solo .riv con 17 animaciones generadas a partir de tu personaje o logo en unos minutos, conectadas a una máquina de estados: CharacterStateMachine con un input numérico mood (0 idle, 1 happy, 2 wave, 3 thinking, 4 sad, 5 loading, 6 listening, 7 talking, 8 sleeping, 9 attention) y los triggers success, error, yes, no, enter y exit, además de un view model Character para Data Binding. Para usar esos estados de ánimo en FlutterFlow, crea el widget personalizado que se muestra abajo.
¿Cómo controlo el número de mood con un widget personalizado?
En Custom Code, agrega el paquete rive como dependencia (consulta en pub.dev la versión actual del paquete rive) y luego crea un widget personalizado con un parámetro entero mood. El widget carga el archivo una sola vez, busca los inputs y los actualiza cada vez que FlutterFlow le pasa un valor nuevo:
class RiveMascot extends StatefulWidget {
const RiveMascot({super.key, this.width, this.height, required this.mood});
final double? width;
final double? height;
final int mood;
@override
State<RiveMascot> createState() => _RiveMascotState();
}
class _RiveMascotState extends State<RiveMascot> {
File? file;
RiveWidgetController? controller;
NumberInput? mood;
@override
void initState() {
super.initState();
_load();
}
Future<void> _load() async {
final f = await File.asset('assets/rive_animations/character.riv',
riveFactory: Factory.rive);
if (f == null || !mounted) return;
final c = RiveWidgetController(f,
stateMachineSelector: StateMachineSelector.byName('CharacterStateMachine'));
setState(() {
file = f;
controller = c;
mood = c.stateMachine.number('mood')?..value = widget.mood.toDouble();
});
}
@override
void didUpdateWidget(RiveMascot old) {
super.didUpdateWidget(old);
if (old.mood != widget.mood) mood?.value = widget.mood.toDouble();
}
@override
void dispose() {
mood?.dispose();
controller?.dispose();
file?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final c = controller;
return SizedBox(width: widget.width, height: widget.height,
child: c == null ? null : RiveWidget(controller: c, fit: Fit.contain));
}
}
Revisa la ruta que FlutterFlow asigna a los archivos subidos en tu proyecto y ejecuta await RiveNative.init(); una sola vez antes de cargar cualquier archivo, por ejemplo en una acción personalizada agregada a main.dart. Vincula mood a una variable de estado de la página o de la app; al cambiar esa variable, cambia el loop.
¿Cómo disparo las reacciones de éxito y error?
Los triggers son eventos, así que no encajan bien en un parámetro de widget. Un patrón simple y confiable es usar un parámetro contador por cada trigger: cuando el entero aumenta, el widget dispara el trigger.
// extra parameter: final int successCount;
TriggerInput? success; // in _load(): success = c.stateMachine.trigger('success');
@override
void didUpdateWidget(RiveMascot old) {
super.didUpdateWidget(old);
if (old.mood != widget.mood) mood?.value = widget.mood.toDouble();
if (widget.successCount > old.successCount) success?.fire();
}
En el action flow, después de que la llamada a tu backend tenga éxito, incrementa en uno la variable de estado successCount. Agrega un errorCount de la misma forma. Libera cada input en dispose().
Estas llamadas usan la API de inputs heredada de Rive, que Rive marcó como obsoleta en favor de Data Binding, pero que el runtime de Flutter sigue admitiendo para archivos existentes. Un archivo con view models también se puede controlar con la API de Data Binding de Flutter mediante CharacterViewModelMachine; la estructura del widget no cambia. La sección de Flutter de la guía de runtimes de Rive muestra la configuración completa del runtime.
¿Cuándo conviene usar el widget LottieAnimation?
Úsalo cuando la animación se reproduzca siempre igual. El widget LottieAnimation de FlutterFlow muestra archivos Lottie desde assets subidos o una URL, y una acción Lottie Animation puede iniciarla y pausarla. No requiere código personalizado.
- Casos ideales: un spinner de carga, una marca de éxito después del checkout, una ilustración de onboarding, un loop de estado vacío.
- Casos poco adecuados: un personaje que cambia de estado de ánimo según el estado de la app o que reacciona a varios eventos distintos. Con Lottie tendrías que cambiar archivos o segmentos y sincronizar tú mismo las transiciones.
Muchas apps usan ambos: Lottie para pequeños momentos decorativos y un personaje de Rive, controlado por un widget personalizado, para los momentos que necesitan personalidad. Si solo necesitas un clip fijo, un video en loop sin sonido también funciona y no requiere ningún runtime de animación.
Cómo controlar una máquina de estados de Rive en FlutterFlow
- Agrega el paquete. En Custom Code, agrega el paquete
rivecomo dependencia. - Sube el archivo. Sube el .riv como asset y anota su ruta.
- Crea el widget. Crea un widget personalizado con un parámetro entero
moodque cargue el archivo conCharacterStateMachine. - Inicializa el runtime. Llama a
RiveNative.init()una sola vez al arrancar, antes de cargar cualquier archivo. - Vincula el estado. Vincula
mooda una variable de estado y actualízala desde los action flows. - Agrega triggers. Agrega parámetros contadores que disparen
successyerroral incrementarse.
Preguntas frecuentes
¿Puedo usar una máquina de estados de Rive en FlutterFlow sin código?
No, según la documentación de FlutterFlow. El widget integrado RiveAnimation documenta la selección de artboard y de animación, además de una acción de reproducción, pero no menciona inputs de la máquina de estados ni view models. Para cambiar un estado de ánimo o disparar triggers desde la lógica de tu app, envuelve el paquete de Flutter rive en un widget personalizado.
¿Por qué mi archivo de Rive solo muestra su primer estado en FlutterFlow?
El widget integrado reproduce animaciones seleccionadas, no una máquina de estados controlada por inputs. Un archivo cuyos loops se eligen con un input numérico se queda en su estado predeterminado porque nada asigna ese número. Un widget personalizado que asigne el input mood o la propiedad del view model lo soluciona.
¿Los widgets personalizados de Rive funcionan en las compilaciones web de FlutterFlow?
El paquete rive es compatible con Flutter web, además de iOS y Android, así que el mismo widget personalizado puede ejecutarse en una compilación web. Pruébalo en una compilación desplegada real, ya que el código personalizado puede no renderizarse en todos los modos de vista previa de FlutterFlow, y revisa los tiempos de carga del runtime en la web.
Respuestas rápidas de esta guía
Fuentes
- RiveAnimation widget, FlutterFlow Docs
- LottieAnimation widget, FlutterFlow Docs
- Rive animations with State Machine, FlutterFlow Community
- Flutter runtime, Rive
- Flutter runtime: Inputs (legacy), Rive
- rive package, pub.dev