在实现 UI 设计时,我们经常需要在屏幕上显示或隐藏各种元素。如若这个过程只是让某个元素快速地出现或者消失,用户们肯定不买帐。我们一般会使用不透明动画让元素淡入淡出,以创建出更加流畅的用户体验。

在 Flutter 中,你可以使用 AnimatedOpacity Widget 来完成这个效果。

步骤

  • 创建一个用来淡入淡出的方框

  • 定义一个 StatefulWidget

  • 显示一个用于切换可见状态的按钮

  • 淡入淡出方框

1. 创建一个用来淡入淡出的方框

首先你需要一些用来淡入淡出的东西。在这个示例中,你将在屏幕上绘制一个绿色的方框。

  1. Container(
  2. width: 200.0,
  3. height: 200.0,
  4. color: Colors.green,
  5. );

2. 定义一个 StatefulWidget

我们要对这个绿色的方框进行动画。那么为了表示这个方框的状态是否可见,你需要使用 StatefulWidget

StatefulWidget 是一个类,它将会创建一个 State 对象。而这个 State 对象将包含与这个应用相关的一些数据,并且能够更新它们。当你更新数据时,可以让Flutter使用这些更改去重建用户界面。

在这个示例中,我们将使用一个布尔值来表示其是否可见。

要构造一个 StatefulWidget,你需要创建两个类:一个 StatefulWidget 类以及与其对应的 State 类。小提示:Android Studio 和 VSCode 的 Flutter 插件都包含了 stful 片段,能够快速生成该代码。

  1. // The StatefulWidget's job is to take in some data and create a State class.
  2. // In this case, our Widget takes in a title, and creates a _MyHomePageState.
  3. class MyHomePage extends StatefulWidget {
  4. final String title;
  5. MyHomePage({Key key, this.title}) : super(key: key);
  6. @override
  7. _MyHomePageState createState() => _MyHomePageState();
  8. }
  9. // The State class is responsible for two things: holding some data you can
  10. // update and building the UI using that data.
  11. class _MyHomePageState extends State<MyHomePage> {
  12. // Whether the green box should be visible or invisible
  13. bool _visible = true;
  14. @override
  15. Widget build(BuildContext context) {
  16. // The green box goes here with some other Widgets.
  17. }
  18. }

3. 显示一个用于切换可见状态的按钮

现在你已经有了一些数据能够决定这个绿色方框是否可见,但是还需要一个方法来改变这些数据。在这个例子中,我们想让方框在显示与隐藏之间切换。

为此你将使用一个按钮。当用户按下按钮时,数据将会在 true 和 false 之间进行切换。为了使改变生效,你需要使用 State 类中的 setState 方法,这会使 Flutter 重建这个小部件。

注意:如果你想要了解更多与用户输入相关的资料,请参阅 Cookbook 的 Gestures 部分。

  1. FloatingActionButton(
  2. onPressed: () {
  3. // Make sure to call setState. This tells Flutter to rebuild the
  4. // UI with the changes.
  5. setState(() {
  6. _visible = !_visible;
  7. });
  8. },
  9. tooltip: 'Toggle Opacity',
  10. child: Icon(Icons.flip),
  11. );

4. 淡入淡出方框

现在你的屏幕上已经有一个绿色的方框,以及一个可以通过改变 truefalse 来切换方框可见性的按钮。那么该如何让方框淡入淡出呢?答案是使用 AnimatedOpacity Widget。

AnimatedOpacity 小部件需要传入三个参数:

  • opacity:它的取值范围从 0.0(不可见)到 1.0(完全可见)。

  • duration:代表这个动画需要持续多长时间。

  • child:需要进行动画的小部件。在这个例子中就是那个绿色的方框。

  1. AnimatedOpacity(
  2. // If the Widget should be visible, animate to 1.0 (fully visible). If
  3. // the Widget should be hidden, animate to 0.0 (invisible).
  4. opacity: _visible ? 1.0 : 0.0,
  5. duration: Duration(milliseconds: 500),
  6. // The green box needs to be the child of the AnimatedOpacity
  7. child: Container(
  8. width: 200.0,
  9. height: 200.0,
  10. color: Colors.green,
  11. ),
  12. );

一个完整的例子

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. final appTitle = 'Opacity Demo';
  7. return MaterialApp(
  8. title: appTitle,
  9. home: MyHomePage(title: appTitle),
  10. );
  11. }
  12. }
  13. // The StatefulWidget's job is to take in some data and create a State class.
  14. // In this case, the Widget takes a title, and creates a _MyHomePageState.
  15. class MyHomePage extends StatefulWidget {
  16. final String title;
  17. MyHomePage({Key key, this.title}) : super(key: key);
  18. @override
  19. _MyHomePageState createState() => _MyHomePageState();
  20. }
  21. // The State class is responsible for two things: holding some data you can
  22. // update and building the UI using that data.
  23. class _MyHomePageState extends State<MyHomePage> {
  24. // Whether the green box should be visible or invisible
  25. bool _visible = true;
  26. @override
  27. Widget build(BuildContext context) {
  28. return Scaffold(
  29. appBar: AppBar(
  30. title: Text(widget.title),
  31. ),
  32. body: Center(
  33. child: AnimatedOpacity(
  34. // If the Widget should be visible, animate to 1.0 (fully visible).
  35. // If the Widget should be hidden, animate to 0.0 (invisible).
  36. opacity: _visible ? 1.0 : 0.0,
  37. duration: Duration(milliseconds: 500),
  38. // The green box needs to be the child of the AnimatedOpacity
  39. child: Container(
  40. width: 200.0,
  41. height: 200.0,
  42. color: Colors.green,
  43. ),
  44. ),
  45. ),
  46. floatingActionButton: FloatingActionButton(
  47. onPressed: () {
  48. // Make sure to call setState. This tells Flutter to rebuild the
  49. // UI with the changes.
  50. setState(() {
  51. _visible = !_visible;
  52. });
  53. },
  54. tooltip: 'Toggle Opacity',
  55. child: Icon(Icons.flip),
  56. ), // This trailing comma makes auto-formatting nicer for build methods.
  57. );
  58. }
  59. }

一个淡入淡出的例子