Como Usar o Widget Hero no Flutter para Animações de Transição
Introdução
O widget Hero
no Flutter é uma ferramenta poderosa para criar transições animadas suaves entre telas. Ele é especialmente útil quando você deseja que um elemento mantenha sua aparência ao navegar entre páginas, proporcionando uma experiência visualmente fluida.
Neste tutorial, vamos explorar o uso do Hero
para criar animações de transição entre telas e aprimorar a experiência do usuário.
—
1. O Que é o Widget Hero?
O Hero
é um widget que permite a animação entre duas páginas ao usar a mesma tag. Quando um widget envolvido em um Hero
é navegado para outra tela, ele realiza uma transição suave para a nova posição.
Isso é particularmente útil para criar efeitos visuais impressionantes ao navegar em listas, imagens e outros elementos de UI.
—
2. Implementando um Hero Básico
Vamos começar com um exemplo simples de transição entre duas telas usando o Hero
.
Passo 1: Criando a Tela Inicial
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Hero Example')),
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DetailScreen(),
),
);
},
child: Hero(
tag: 'hero-tag',
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.network(
'https://source.unsplash.com/random/200x200',
width: 100,
height: 100,
),
),
),
),
),
);
}
}
Passo 2: Criando a Tela de Detalhes
class DetailScreen extends StatelessWidget {
const DetailScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Detalhes')),
body: Center(
child: Hero(
tag: 'hero-tag',
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.network(
'https://source.unsplash.com/random/200x200',
width: 300,
height: 300,
),
),
),
),
);
}
}
Nesse exemplo, a imagem da tela inicial se expande suavemente para a tela de detalhes.
—
3. Melhorando a Animação
O Flutter permite personalizar a animação do Hero
para que fique mais fluida e sofisticada. Podemos modificar a animação adicionando um FlightShuttleBuilder
para controlar a aparência durante a transição.
Hero(
tag: 'hero-tag',
flightShuttleBuilder: (flightContext, animation, direction, fromContext, toContext) {
return ScaleTransition(
scale: animation.drive(Tween(begin: 0.5, end: 1.0)),
child: toContext.widget,
);
},
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.network(
'https://source.unsplash.com/random/200x200',
width: 100,
height: 100,
),
),
)
Com isso, a imagem escala suavemente durante a animação.
—
4. Hero com ListView
O Hero
também pode ser usado dentro de listas para criar transições suaves entre itens de uma lista e uma página de detalhes.
class HomeScreen extends StatelessWidget {
final List images = List.generate(
10,
(index) => 'https://source.unsplash.com/random/200x200?sig=$index',
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Lista de Imagens')),
body: ListView.builder(
itemCount: images.length,
itemBuilder: (context, index) {
return ListTile(
leading: Hero(
tag: 'hero-tag-$index',
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
images[index],
width: 50,
height: 50,
),
),
),
title: Text('Imagem $index'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(imageUrl: images[index], tag: 'hero-tag-$index'),
),
);
},
);
},
),
);
}
}
class DetailScreen extends StatelessWidget {
final String imageUrl;
final String tag;
const DetailScreen({Key? key, required this.imageUrl, required this.tag}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Detalhes')),
body: Center(
child: Hero(
tag: tag,
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.network(imageUrl, width: 300, height: 300),
),
),
),
);
}
}
—
5. Boas Práticas
- Garanta que a
tag
do Hero seja única para cada transição. - Use o
FlightShuttleBuilder
para personalizar a animação. - Evite mudanças drásticas no tamanho do widget para manter a animação fluida.
Publicar comentário