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

系列文章

  1. Flutter 旋转动画 — RotationTransition
  2. Flutter 平移动画 — 4种实现方式
  3. Flutter 淡入淡出与逐渐出现动画
  4. Flutter 尺寸缩放、形状、颜色、阴影变换动画
  5. Flutter 列表Item动画 — AnimatedList实现Item左进左出、淡入淡出
  6. Flutter Hero 实现共享元素转场动画
  7. Flutter Hero 实现径向变换动画 — 圆形变成矩形的转场动画
  8. Flutter 自定义动画 — 数字递增动画和文字逐行逐字出现或消失动画


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),
    );
  }

动画效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/ww897532167/article/details/125442767
今日推荐