Dica#1

Dê vida às animações com Spring

Uma mola (Spring) é como as coisas se movem na vida real. Quando você puxa um elástico e solta, ele não para instantaneamente. Ele volta ao normal, oscila um pouco e depois se estabiliza. O Flutter permite que você faça animações se moverem dessa forma, em vez de simplesmente percorrer uma duração fixa.

A mola do Flutter possui 3 propriedades:

SpringDescription(
  mass: 0.5,
  stiffness: 200,
  damping: 12.5,
)
  • mass controla o peso do objeto. Quanto maior a massa, mais inércia ele possui.
  • stiffness define a força da mola. Quanto maior, mais rapidamente ela tenta voltar ao destino.
  • damping controla quanto da energia é perdida durante o movimento. Valores menores geram mais bounce; valores maiores fazem a animação estabilizar mais rapidamente.

Nosso exemplo

No exemplo abaixo temos um PageView exibindo uma lista de extratos.

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

  List<Statement> get _statements => generateStatements(count: 5);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        physics: const SnappyPagePhysics(),
        children: [
          for (final statement in _statements)
            StatementCard(statement: statement),
        ],
      ),
    );
  }
}

Perceba que a única diferença para um PageView comum é esta linha:

physics: const SnappyPagePhysics(),

É ela que define como a página deve se comportar quando o usuário termina o gesto de deslizar.


Criando uma Spring personalizada

Para alterar esse comportamento, basta criar uma classe que herda de PageScrollPhysics e sobrescrever o getter spring.

class SnappyPagePhysics extends PageScrollPhysics {
  const SnappyPagePhysics({super.parent});

  @override
  SpringDescription get spring {
    return SpringDescription(
      mass: 0.5,
      stiffness: 200,
      damping: 12.5,
    );
  }

  @override
  SnappyPagePhysics applyTo(ScrollPhysics? ancestor) {
    return SnappyPagePhysics(
      parent: buildParent(ancestor),
    );
  }
}

Sempre que o PageView precisar encaixar uma página, ele utilizará essa configuração em vez da Spring padrão do Flutter.


Entendendo nossa configuração

Escolhemos a seguinte combinação:

SpringDescription(
  mass: 0.5,
  stiffness: 200,
  damping: 12.5,
)

mass: 0.5

Uma massa baixa deixa a troca entre páginas leve e responsiva.

mass: 0.5

Se aumentarmos esse valor para 2.0, o movimento passa a transmitir mais peso e demora mais para acelerar e desacelerar.


stiffness: 200

A rigidez controla a velocidade com que a página “encaixa” no destino.

stiffness: 200

É um valor equilibrado: rápido o suficiente para parecer responsivo, mas sem parecer brusco.

Valores menores deixam o movimento mais suave; valores maiores fazem a página praticamente grudar no destino.


damping: 12.5

O amortecimento controla o bounce.

damping: 12.5

Esse valor cria uma pequena elasticidade antes da página estabilizar.

Se diminuirmos para algo como 5, haverá um bounce bem mais evidente.

Se aumentarmos para 30, a página praticamente para assim que chega ao destino.


O que acontece durante o swipe?

Enquanto o usuário arrasta a tela, o PageView continua acompanhando normalmente o dedo.

A diferença aparece quando ele solta.

Sem nenhuma configuração personalizada, o Flutter utiliza a Spring padrão da plataforma.

Com:

physics: const SnappyPagePhysics(),

o PageView passa a utilizar a nossa própria configuração:

SpringDescription(
  mass: 0.5,
  stiffness: 200,
  damping: 12.5,
)

Isso significa que toda troca de página passa a ter exatamente a personalidade que definimos, sem precisar criar AnimationController, GestureDetector ou SpringSimulation.


E o applyTo?

Você provavelmente reparou neste método:

@override
SnappyPagePhysics applyTo(ScrollPhysics? ancestor) {
  return SnappyPagePhysics(
    parent: buildParent(ancestor),
  );
}

Ele permite que o Flutter combine sua ScrollPhysics com outras físicas de rolagem quando necessário.

Na prática, quase sempre basta manter essa implementação exatamente como está.


Uma pequena mudança, uma grande diferença

Personalizar a Spring do PageView exige apenas uma única classe, mas muda completamente a sensação da interface.

Em vez de simplesmente trocar de página, o componente passa a responder com uma física própria, tornando a navegação muito mais agradável e natural para o usuário.