Flutter Hero 实现共享元素转场动画

系列文章

  1. Flutter 旋转动画 — RotationTransition
  2. Flutter 平移动画 — 4种实现方式
  3. Flutter 淡入淡出与逐渐出现动画
  4. Flutter 尺寸缩放、形状、颜色、阴影变换动画
  5. Flutter 列表Item动画 — AnimatedList实现Item左进左出、淡入淡出
  6. Flutter Hero 实现共享元素转场动画

文章目录

  • 系列文章
  • 1 动画效果
  • 2 Hero介绍
  • 3 未使用Hero时的页面切换
  • 4 使用Hero实现的转场动画


1 动画效果


2 Hero介绍

Hero 是Flutter提供的一个可以实现子Widget在页面切换时带有飞行效果的Widget,可实现元素共享动画效果。

实现方式:在2个页面之间,都使用Hero包裹子控件并设置相关的tag标识即可。

注意:同一个页面中不能使用多个相同的Hero Tag

3 未使用Hero时的页面切换

列表页面

class ListPage extends StatefulWidget {
  const ListPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _ListPageState();
}

class _ListPageState extends State<ListPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('列表页'), centerTitle: true),
      body: GridView.count(
        crossAxisCount: 2,
        children: List.generate(10, _buildItem),
      ),
    );
  }

  Widget _buildItem(int index) {
    return CupertinoButton(
      padding: EdgeInsets.zero,
      onPressed: () {
        Navigator.of(context).push(
          MaterialPageRoute(builder: (context) => DetailPage(index: index)),
        );
      },
      child: _buildImageWidget(index),
    );
  }

  // 列表页的Image size是120
  Widget _buildImageWidget(int index) {
    return const FlutterLogo(size: 120);
  }
}

详情页面

class DetailPage extends StatefulWidget {
  final int index;

  const DetailPage({Key? key, required this.index}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _DetailPageState();
}

class _DetailPageState extends State<DetailPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('详情页'), centerTitle: true),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const SizedBox(height: 12),
            _buildImageWidget(widget.index),
            const SizedBox(height: 12),
            Text(
              ' ${widget.index} :登高(作者:杜甫)',
              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
            ),
            const SizedBox(height: 12),
            const Text(
              '风急天高猿啸哀,\n渚清沙白鸟飞回。\n无边落木萧萧下,\n不尽长江滚滚来。'
              '\n万里悲秋常作客,\n百年多病独登台。\n艰难苦恨繁霜鬓,\n潦倒新停浊酒杯。\n',
              textAlign: TextAlign.center,
              style: TextStyle(color: Colors.black, fontSize: 15),
            ),
          ],
        ),
      ),
    );
  }

  // 详情页的Image size是250
  Widget _buildImageWidget(int index) {
    return const FlutterLogo(size: 250);
  }
}

效果图


4 使用Hero实现的转场动画

实现Widget切换页面时飞到下一页的动画,使用Hero Widget包裹列表与详情页的图片Widget,并设置相同的tag即可。
修改 _buildImageWidget,使用Hero包裹FlutterLogo,并传入唯一的tag

列表页

  // 列表页的Image size是120
  Widget _buildImageWidget(int index) {
    // 同一页面的hero不能有多个相同tag
    return Hero(
      tag: 'hero_tag_$index',
      child: const FlutterLogo(size: 120),
    );
  }

详情页

  // 详情页的Image size是250
  Widget _buildImageWidget(int index) {
    return Hero(
      tag: 'hero_tag_$index',
      child: const FlutterLogo(size: 250),
    );
  }

动画效果

你可能感兴趣的:(Flutter,flutter,Hero,共享元素动画,转场动画)