大家好,近期我们会开始连载 Flutter 中文文档的 Cookbook 部分,中文我们称之为实用教程,总共分动画、设计、网络请求、数据库设计、插件和测试等 12 章,共计 50 多小节,每天更新一篇。感谢社区的译者对中文文档做出的翻译和贡献,你可以阅读原文查看中文文档,我们期待你参与提出疑问和修改建议。
在实现 UI 设计时,我们经常需要在屏幕上显示或隐藏各种元素。如若这个过程只是让某个元素快速地出现或者消失,用户们肯定不买帐。我们一般会使用不透明动画让元素淡入淡出,以创建出更加流畅的用户体验。
在 Flutter 中,你可以使用 AnimatedOpacity
widget 来完成这个效果,请参见下面的步骤。
步骤
创建一个用来淡入淡出的方框
定义一个 StatefulWidget
显示一个用于切换可见状态的按钮
淡入淡出方框
创建一个用来淡入淡出的方框
首先是创建一个来淡入淡出的东西。在这个示例中,你将在屏幕上绘制一个绿色的方框。
Container(
width: 200.0,
height: 200.0,
color: Colors.green,
);
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.
}
}
现在你已经有了一些数据能够决定这个绿色方框是否可见,但是还需要一个方法来改变这些数据。在这个例子中,我们想让方框在显示与隐藏之间切换。
为此你将使用一个按钮——当用户按下按钮时,数据将会在 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),
);
现在你的屏幕上已经有一个绿色的方框,以及一个可以通过改变 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.
);
}
}
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8