动画实用教程 | Widget 的淡入淡出效果

大家好,近期我们会开始连载 Flutter 中文文档的 Cookbook 部分,中文我们称之为实用教程,总共分动画、设计、网络请求、数据库设计、插件和测试等 12 章,共计 50 多小节,每天更新一篇。感谢社区的译者对中文文档做出的翻译和贡献,你可以阅读原文查看中文文档,我们期待你参与提出疑问和修改建议。

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

在 Flutter 中,你可以使用 AnimatedOpacity widget 来完成这个效果,请参见下面的步骤。

步骤

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

  2. 定义一个 StatefulWidget

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

  4. 淡入淡出方框

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

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

Container(

  width: 200.0,

  height: 200.0,

  color: Colors.green,

);

  1. 定义一个 StatefulWidget

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

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

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

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

// The StatefulWidget's job is to take data and create a State class.

// In this case, the widget takes a title, and creates a _MyHomePageState.

class MyHomePage extends StatefulWidget {

  final String title;



  MyHomePage({Key key, this.title}) : super(key: key);



  @override

  _MyHomePageState createState() => _MyHomePageState();

}



// The State class is responsible for two things: holding some data you can

// update and building the UI using that data.

class _MyHomePageState extends State<MyHomePage> {

  // Whether the green box should be visible.

  bool _visible = true;



  @override

  Widget build(BuildContext context) {

    // The green box goes here with some other Widgets.

  }

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

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

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

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

相关链接:https://flutter-io.cn/docs/cookbook#gestures

FloatingActionButton(

  onPressed: () {

    // Call setState. This tells Flutter to rebuild the

    // UI with the changes.

    setState(() {

      _visible = !_visible;

    });

  },

  tooltip: 'Toggle Opacity',

  child: Icon(Icons.flip),

);
  1. 淡入淡出方框

现在你的屏幕上已经有一个绿色的方框,以及一个可以通过改变 true 或 false 来切换方框可见性的按钮。那么该如何让方框淡入淡出呢?答案是使用 AnimatedOpacity widget。AnimatedOpacity widget 需要传入三个参数:

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

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

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

AnimatedOpacity(

  // If the widget is visible, animate to 0.0 (invisible).

  // If the widget is hidden, animate to 1.0 (fully visible).

  opacity: _visible ? 1.0 : 0.0,

  duration: Duration(milliseconds: 500),

  // The green box must be a child of the AnimatedOpacity widget.

  child: Container(

    width: 200.0,

    height: 200.0,

    color: Colors.green,

  ),

);

完整样例

import 'package:flutter/material.dart';



void main() => runApp(MyApp());



class MyApp extends StatelessWidget {

  @override

  Widget build(BuildContext context) {

    final appTitle = 'Opacity Demo';

    return MaterialApp(

      title: appTitle,

      home: MyHomePage(title: appTitle),

    );

  }

}



// The StatefulWidget's job is to take data and create a State class.

// In this case, the widget takes a title, and creates a _MyHomePageState.

class MyHomePage extends StatefulWidget {

  final String title;



  MyHomePage({Key key, this.title}) : super(key: key);



  @override

  _MyHomePageState createState() => _MyHomePageState();

}



// The State class is responsible for two things: holding some data you can

// update and building the UI using that data.

class _MyHomePageState extends State<MyHomePage> {

  // Whether the green box should be visible

  bool _visible = true;



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(

        title: Text(widget.title),

      ),

      body: Center(

        child: AnimatedOpacity(

          // If the widget is visible, animate to 0.0 (invisible).

          // If the widget is hidden, animate to 1.0 (fully visible).

          opacity: _visible ? 1.0 : 0.0,

          duration: Duration(milliseconds: 500),

          // The green box must be a child of the AnimatedOpacity widget.

          child: Container(

            width: 200.0,

            height: 200.0,

            color: Colors.green,

          ),

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: () {

          // Call setState. This tells Flutter to rebuild the

          // UI with the changes.

          setState(() {

            _visible = !_visible;

          });

        },

        tooltip: 'Toggle Opacity',

        child: Icon(Icons.flip),

      ), // This trailing comma makes auto-formatting nicer for build methods.

    );

  }

}

最多阅读

在Flutter中添加资源和图片 1年以前  |  1921次阅读
发布Flutter开发的iOS程序 1年以前  |  1338次阅读
Flutter Widget框架概述 1年以前  |  1166次阅读
在Flutter中发起HTTP网络请求 1年以前  |  1120次阅读
JSON和序列化 1年以前  |  1054次阅读
使用Inspector检查用户界面 1年以前  |  1032次阅读
Flutter框架概览 1年以前  |  982次阅读
为Flutter应用程序添加交互 1年以前  |  952次阅读
使用自定义字体 1年以前  |  949次阅读
Flutter的手势GestureDetector分析详解 8月以前  |  936次阅读
Flutter插件详解及其发布插件 8月以前  |  886次阅读
处理文本输入 1年以前  |  834次阅读
发布Flutter开发的Android程序 1年以前  |  763次阅读
使用包来开发Flutter应用 1年以前  |  759次阅读
Flutter 状态管理指南之 Provider 8月以前  |  739次阅读
编写国际化Flutter App 1年以前  |  735次阅读
Dart 语法预览 1年以前  |  717次阅读
使用平台通道编写平台特定的代码 1年以前  |  703次阅读
Flutter路由详解 8月以前  |  644次阅读