动画化容器的属性
如何使用隐式动画为容器的属性添加动画。
Container 类提供了一种简便的方法来创建具有特定属性(如宽度、高度、背景颜色、内边距、边框等)的小部件。
简单的动画通常涉及随时间改变这些属性。例如,你可能希望将背景颜色从灰色渐变为绿色,以指示用户已选中某项。
为了实现这些属性的动画,Flutter 提供了 AnimatedContainer 小部件。与 Container 小部件类似,AnimatedContainer 允许你定义宽度、高度、背景颜色等。然而,当 AnimatedContainer 使用新属性重新构建时,它会自动在旧值和新值之间进行动画过渡。在 Flutter 中,这类动画被称为“隐式动画”。
本指南通过以下步骤介绍如何使用 AnimatedContainer 在用户点击按钮时实现尺寸、背景颜色和圆角的动画效果:
- 创建一个具有默认属性的 StatefulWidget。
- 使用这些属性构建一个
AnimatedContainer。 - 通过使用新属性重新构建来启动动画。
1. 创建一个具有默认属性的 StatefulWidget
#首先,创建 StatefulWidget 和 State 类。使用自定义的 State 类来定义随时间变化的属性。在这个示例中,包括宽度、高度、颜色和圆角。你还可以定义每个属性的默认值。
这些属性属于自定义的 State 类,以便在用户点击按钮时可以更新它们。
class AnimatedContainerApp extends StatefulWidget {
const AnimatedContainerApp({super.key});
@override
State<AnimatedContainerApp> createState() => _AnimatedContainerAppState();
}
class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
// Define the various properties with default values. Update these properties
// when the user taps a FloatingActionButton.
double _width = 50;
double _height = 50;
Color _color = Colors.green;
BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);
@override
Widget build(BuildContext context) {
// Fill this out in the next steps.
}
}
2. 使用这些属性构建一个 AnimatedContainer
#
接下来,使用上一步定义的属性构建 AnimatedContainer。此外,提供一个 duration(持续时间)来定义动画运行的时长。
AnimatedContainer(
// Use the properties stored in the State class.
width: _width,
height: _height,
decoration: BoxDecoration(
color: _color,
borderRadius: _borderRadius,
),
// Define how long the animation should take.
duration: const Duration(seconds: 1),
// Provide an optional curve to make the animation feel smoother.
curve: Curves.fastOutSlowIn,
)
3. 通过使用新属性重新构建来启动动画
#最后,通过使用新属性重新构建 AnimatedContainer 来启动动画。如何触发重新构建?使用 setState() 方法即可。
在应用中添加一个按钮。当用户点击该按钮时,在 setState() 调用中更新属性,设置新的宽度、高度、背景颜色和圆角。
实际应用通常在固定值之间转换(例如,从灰色背景变为绿色背景)。对于此示例,我们会在用户每次点击按钮时生成新的值。
FloatingActionButton(
// When the user taps the button
onPressed: () {
// Use setState to rebuild the widget with new values.
setState(() {
// Create a random number generator.
final random = Random();
// Generate a random width and height.
_width = random.nextInt(300).toDouble();
_height = random.nextInt(300).toDouble();
// Generate a random color.
_color = Color.fromRGBO(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
1,
);
// Generate a random border radius.
_borderRadius = BorderRadius.circular(
random.nextInt(100).toDouble(),
);
});
},
child: const Icon(Icons.play_arrow),
)
互动示例
#import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(const AnimatedContainerApp());
class AnimatedContainerApp extends StatefulWidget {
const AnimatedContainerApp({super.key});
@override
State<AnimatedContainerApp> createState() => _AnimatedContainerAppState();
}
class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
// Define the various properties with default values. Update these properties
// when the user taps a FloatingActionButton.
double _width = 50;
double _height = 50;
Color _color = Colors.green;
BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('AnimatedContainer Demo')),
body: Center(
child: AnimatedContainer(
// Use the properties stored in the State class.
width: _width,
height: _height,
decoration: BoxDecoration(
color: _color,
borderRadius: _borderRadius,
),
// Define how long the animation should take.
duration: const Duration(seconds: 1),
// Provide an optional curve to make the animation feel smoother.
curve: Curves.fastOutSlowIn,
),
),
floatingActionButton: FloatingActionButton(
// When the user taps the button
onPressed: () {
// Use setState to rebuild the widget with new values.
setState(() {
// Create a random number generator.
final random = Random();
// Generate a random width and height.
_width = random.nextInt(300).toDouble();
_height = random.nextInt(300).toDouble();
// Generate a random color.
_color = Color.fromRGBO(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
1,
);
// Generate a random border radius.
_borderRadius = BorderRadius.circular(
random.nextInt(100).toDouble(),
);
});
},
child: const Icon(Icons.play_arrow),
),
),
);
}
}