Skip to main content

在屏幕之间为小部件添加动画

在用户在屏幕之间导航时,引导用户浏览应用程序通常很有帮助。引导用户浏览应用程序的一种常用技术是从一个屏幕到下一个屏幕为小部件添加动画。这会创建一个连接两个屏幕的视觉锚点。

使用 Hero 小部件在一个屏幕到另一个屏幕之间为小部件添加动画。 此方法使用以下步骤:

  1. 创建两个显示相同图像的屏幕。
  2. 向第一个屏幕添加 Hero 小部件。
  3. 向第二个屏幕添加 Hero 小部件。

1. 创建两个显示相同图像的屏幕

#

在此示例中,在两个屏幕上都显示相同的图像。当用户点击图像时,将图像从第一个屏幕动画到第二个屏幕。现在,创建可视化结构;在接下来的步骤中处理动画。

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Main Screen'),
      ),
      body: GestureDetector(
        onTap: () {
          Navigator.push(context, MaterialPageRoute(builder: (context) {
            return const DetailScreen();
          }));
        },
        child: Image.network(
          'https://picsum.photos/250?image=9',
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: Center(
          child: Image.network(
            'https://picsum.photos/250?image=9',
          ),
        ),
      ),
    );
  }
}

2. 向第一个屏幕添加 Hero 小部件

#

要使用动画将两个屏幕连接在一起,请将两个屏幕上的 Image 小部件都包装在 Hero 小部件中。 Hero 小部件需要两个参数:

tag
用于标识 Hero 的对象。 它在两个屏幕上必须相同。
child
要在屏幕之间添加动画的小部件。
dart
Hero(
  tag: 'imageHero',
  child: Image.network(
    'https://picsum.photos/250?image=9',
  ),
)

3. 向第二个屏幕添加 Hero 小部件

#

要与第一个屏幕完成连接,请使用与第一个屏幕中的 Hero 具有相同 tagHero 小部件包装第二个屏幕上的 Image

应用 Hero 小部件到第二个屏幕后,屏幕之间的动画就会生效。

dart
Hero(
  tag: 'imageHero',
  child: Image.network(
    'https://picsum.photos/250?image=9',
  ),
)

交互式示例

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

void main() => runApp(const HeroApp());

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Transition Demo',
      home: MainScreen(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Main Screen'),
      ),
      body: GestureDetector(
        onTap: () {
          Navigator.push(context, MaterialPageRoute(builder: (context) {
            return const DetailScreen();
          }));
        },
        child: Hero(
          tag: 'imageHero',
          child: Image.network(
            'https://picsum.photos/250?image=9',
          ),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          Navigator.pop(context);
        },
        child: Center(
          child: Hero(
            tag: 'imageHero',
            child: Image.network(
              'https://picsum.photos/250?image=9',
            ),
          ),
        ),
      ),
    );
  }
}