Perché Rive?

Quando si parla di animazioni vettoriali in Flutter, il pensiero corre subito a Lottie. Tuttavia esiste un'alternativa sempre più matura: Rive. Rive non è solo un formato, ma un intero editor che permette di creare animazioni vettoriali, definire una State Machine e controllarla direttamente dal codice Flutter.

I vantaggi principali rispetto a Lottie sono:

  • File leggeri: i .riv sono spesso più compatti dei JSON di Lottie.
  • Interattività reale: grazie alla State Machine puoi reagire a input dell'utente senza ricaricare l'animazione.
  • Runtime ottimizzato: il rendering avviene tramite il motore Rive, pensato per le performance.
  • Controllo da codice: puoi modificare variabili (inputs) e far cambiare stato all'animazione in tempo reale.

Installazione

Aggiungi il pacchetto al tuo pubspec.yaml:

dependencies:
  rive: ^0.13.1

Poi inserisci il file .riv (esportato dall'editor su rive.app) nella cartella assets e dichiaralo:

flutter:
  assets:
    - assets/animations/hero.riv

Visualizzare una semplice animazione

Il widget più immediato è RiveAnimation.asset, che carica e riproduce un'animazione:

import 'package:flutter/material.dart';
import 'package:rive/rive.dart';

class SimpleRive extends StatelessWidget {
  const SimpleRive({super.key});

  @override
  Widget build(BuildContext context) {
    return const SizedBox(
      height: 250,
      child: RiveAnimation.asset(
        'assets/animations/hero.riv',
        fit: BoxFit.contain,
      ),
    );
  }
}

Di default viene riprodotta la prima animazione presente nel file. Puoi specificarne una particolare con il parametro animations.

Controllare la State Machine

Il vero punto di forza di Rive è la State Machine. Per interagire con essa occorre ottenere i suoi SMIInput. Vediamo un esempio con un input booleano che cambia stato al tocco:

class InteractiveRive extends StatefulWidget {
  const InteractiveRive({super.key});

  @override
  State<InteractiveRive> createState() => _InteractiveRiveState();
}

class _InteractiveRiveState extends State<InteractiveRive> {
  StateMachineController? _controller;
  SMIBool? _isPressed;

  void _onRiveInit(Artboard artboard) {
    final controller = StateMachineController.fromArtboard(
      artboard,
      'State Machine 1',
    );
    if (controller != null) {
      artboard.addController(controller);
      _controller = controller;
      _isPressed = controller.findInput<bool>('pressed') as SMIBool?;
    }
  }

  void _toggle() {
    _isPressed?.value = !(_isPressed?.value ?? false);
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _toggle,
      child: SizedBox(
        height: 200,
        child: RiveAnimation.asset(
          'assets/animations/button.riv',
          stateMachines: const ['State Machine 1'],
          onInit: _onRiveInit,
        ),
      ),
    );
  }
}

Tipi di input disponibili

Rive mette a disposizione tre tipi di input controllabili da codice:

  • SMIBool: stato on/off (es. toggle, hover).
  • SMINumber: valore numerico (es. percentuale di completamento).
  • SMITrigger: impulso istantaneo che scatena una transizione (es. click di conferma).

Esempio con un trigger:

final trigger = controller.findInput<bool>('success') as SMITrigger?;
// In risposta a un evento:
trigger?.fire();

Rive Events: ascoltare gli eventi

Dalle versioni recenti, Rive supporta gli eventi emessi dall'animazione stessa, utili per sincronizzare la logica dell'app con momenti precisi dell'animazione:

controller.addEventListener((event) {
  if (event.name == 'animationComplete') {
    // naviga o aggiorna lo stato
  }
});

Rive vs Lottie: quando scegliere cosa

Aspetto Rive Lottie
Interattività Nativa (State Machine) Limitata
Peso file Generalmente minore Maggiore
Ecosistema designer Editor proprietario After Effects + Bodymovin
Controllo runtime Molto granulare Principalmente playback

Se la tua animazione è puramente decorativa e prodotta da un motion designer in After Effects, Lottie resta una scelta valida. Se invece hai bisogno di interattività o di controllo fine da codice (bottoni animati, onboarding interattivi, mascotte reattive), Rive offre un vantaggio concreto.

Buone pratiche

  • Rilascia sempre il controller nel metodo dispose per evitare memory leak.
  • Verifica i nomi di State Machine e input: devono corrispondere esattamente a quelli definiti nell'editor.
  • Evita troppe State Machine attive contemporaneamente su schermo per non gravare sul rendering.
  • Usa BoxFit appropriato per evitare deformazioni dell'artboard.

Conclusione

Rive porta in Flutter animazioni vettoriali leggere e soprattutto interattive, colmando il limite principale di Lottie. Grazie alle State Machine e agli eventi, puoi costruire interfacce vive che reagiscono all'utente con poche righe di codice. Per progetti che puntano su micro-interazioni curate, vale sicuramente la pena di sperimentarlo.