Flutter页面过渡动画插件hero_animation的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter页面过渡动画插件 hero_animation 的使用

HeroAnimation 是一个用于在同一个路由内实现页面过渡动画的Flutter插件。它允许你将一个子组件从一个布局位置平滑地移动到另一个位置,并且可以在可滚动视图中工作。

如何工作?

你可以通过以下资源了解其具体工作原理:

使用方法

当两个帧之间,具有相同标签的 HeroAnimation 组件的位置发生变化时,就会触发英雄动画。使用 key 来让Flutter框架检测到同一树节点下的 HeroAnimation 重新定位。

HeroAnimationScene 提供了飞行配置给底层的英雄,这些英雄必须是 HeroAnimation 小部件的祖先。

示例代码:在同一棵树节点下重新定位

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

class RepositioningExample extends StatefulWidget {
  @override
  _RepositioningExampleState createState() => _RepositioningExampleState();
}

class _RepositioningExampleState extends State<RepositioningExample> {
  Alignment alignment = Alignment.centerLeft;

  @override
  Widget build(BuildContext context) {
    return HeroAnimationScene(
      duration: const Duration(milliseconds: 500),
      curve: Curves.easeIn,
      child: GestureDetector(
        onTap: () {
          setState(() {
            alignment = Alignment.centerRight;
          });
        },
        child: Align(
          alignment: alignment,
          child: HeroAnimation.child(
            tag: 'tag_0',
            child: const Text('SOME TEXT'),
          ),
        ),
      ),
    );
  }
}

在不同树节点间重新定位

HeroAnimation 允许根据 FlightState 重建其子组件。

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

enum Item { item1, item2, item3 }

extension ItemExtension on Item {
  String getTitle(bool firstFlightEnded) {
    return firstFlightEnded ? "Landed $name" : name;
  }
}

class DifferentTreeNodeExample extends StatefulWidget {
  @override
  _DifferentTreeNodeExampleState createState() => _DifferentTreeNodeExampleState();
}

class _DifferentTreeNodeExampleState extends State<DifferentTreeNodeExample> {
  List<Item> _landedItems = [];
  int _itemPointer = 0;
  Item _currentItem = Item.item1;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        ..._landedItems.map((item) => HeroAnimation.builder(
              tag: item.name,
              builder: (context, flightState, child) {
                final firstFlightEnded = flightState.firstFlightEnded();
                return AnimatedSwitcher(
                  child: Container(
                    alignment: Alignment.centerLeft,
                    key: ValueKey(firstFlightEnded),
                    child: Text(item.getTitle(firstFlightEnded)),
                  ),
                );
              },
            )),
        ElevatedButton(
          onPressed: () {
            setState(() {
              _landedItems.add(_currentItem);
              _itemPointer++;
              _currentItem = Item.values[_itemPointer];
            });
          },
          child: Text('Add Item'),
        )
      ],
    );
  }
}

完整示例 Demo

以下是完整的示例代码,展示了如何在实际应用中使用 HeroAnimation 插件:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            title: TabBar(
              tabs: <Widget>[
                Tab(text: 'Flight state usage'),
                Tab(text: 'Cup Game'),
              ],
            ),
          ),
          body: TabBarView(
            children: <Widget>[
              FlightStateDemoPage(),
              CupGamePage(),
            ],
          ),
        ),
      ),
    );
  }
}

// 这里省略了具体的页面实现细节,例如 FlightStateDemoPage 和 CupGamePage。
// 请参考上面的例子来实现这两个页面。

以上代码展示了如何在一个简单的Flutter应用程序中集成 HeroAnimation 插件,并演示了两种不同的使用场景:在同一棵树节点下重新定位和在不同树节点间重新定位。


更多关于Flutter页面过渡动画插件hero_animation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter页面过渡动画插件hero_animation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用hero_animation插件来实现页面过渡动画的示例代码。不过需要注意的是,实际上Flutter本身已经内置了Hero动画功能,无需额外安装hero_animation插件。因此,以下示例将直接使用Flutter内置的Hero动画功能。

示例代码

1. 创建主页面(MainPage)

import 'package:flutter/material.dart';

class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main Page'),
      ),
      body: Center(
        child: Hero(
          tag: 'heroTag',
          child: Material(
            color: Colors.blue,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(30),
            ),
            child: InkWell(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => DetailPage()),
                );
              },
              child: Container(
                width: 100,
                height: 100,
                child: Center(child: Text('Go to Detail')),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

2. 创建详情页面(DetailPage)

import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Page'),
      ),
      body: Center(
        child: Hero(
          tag: 'heroTag',
          child: Material(
            color: Colors.blue,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(30),
            ),
            child: Container(
              width: 200,
              height: 200,
              child: Center(child: Text('Detail Page')),
            ),
          ),
        ),
      ),
    );
  }
}

3. 主程序入口(main.dart)

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MainPage(),
    );
  }
}

解释

  1. MainPage:在MainPage中,我们创建了一个带有Hero动画的按钮。Herotag属性用于在两个页面之间识别相同的动画对象。当点击按钮时,会导航到DetailPage

  2. DetailPage:在DetailPage中,我们也创建了一个Hero对象,并且使用与MainPage中相同的tag。这样,当从MainPage导航到DetailPage时,Flutter会自动在两个页面之间应用过渡动画。

  3. main.dart:主程序入口,设置了应用程序的主题和初始页面为MainPage

运行效果

当你运行这个应用程序并点击MainPage中的按钮时,你会看到一个带有过渡动画的蓝色方块从MainPage移动到DetailPage,并且在DetailPage中变大。

这个示例展示了如何在Flutter中使用内置的Hero动画功能来实现页面之间的过渡动画,而无需额外的hero_animation插件。

回到顶部