Skip to main content

动画容器属性

Container 类提供了一种方便的方法来创建一个具有特定属性的小部件:宽度、高度、背景颜色、填充、边框等等。

简单的动画通常涉及随着时间的推移更改这些属性。例如,您可能希望将背景颜色从灰色动画到绿色,以指示用户已选择某个项目。

为了动画这些属性,Flutter 提供了AnimatedContainer 小部件。与 Container 小部件类似,AnimatedContainer 允许您定义宽度、高度、背景颜色等等。但是,当 AnimatedContainer 使用新属性重建时,它会自动在旧值和新值之间进行动画转换。在 Flutter 中,这些类型的动画被称为“隐式动画”。

此食谱描述了如何使用 AnimatedContainer 在用户点击按钮时动画大小、背景颜色和边框半径,步骤如下:

  1. 创建一个具有默认属性的 StatefulWidget。
  2. 使用属性构建 AnimatedContainer
  3. 通过使用新属性重建来启动动画。

1. 创建一个具有默认属性的 StatefulWidget

#

首先,创建StatefulWidgetState 类。使用自定义 State 类来定义随时间变化的属性。在此示例中,包括宽度、高度、颜色和边框半径。您还可以定义每个属性的默认值。

这些属性属于自定义 State 类,因此当用户点击按钮时可以更新它们。

dart
class AnimatedContainerApp extends StatefulWidget {
  const AnimatedContainerApp({super.key});

  @override
  State<AnimatedContainerApp> createState() => _AnimatedContainerAppState();
}

class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
  // 定义具有默认值的各种属性。当用户点击 FloatingActionButton 时更新这些属性。
  double _width = 50;
  double _height = 50;
  Color _color = Colors.green;
  BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);

  @override
  Widget build(BuildContext context) {
    // 在接下来的步骤中填写此内容。
  }
}

2. 使用属性构建 AnimatedContainer

#

接下来,使用上一步中定义的属性构建 AnimatedContainer。此外,提供一个 duration 来定义动画应运行多长时间。

dart
AnimatedContainer(
  // 使用 State 类中存储的属性。
  width: _width,
  height: _height,
  decoration: BoxDecoration(
    color: _color,
    borderRadius: _borderRadius,
  ),
  // 定义动画应持续多长时间。
  duration: const Duration(seconds: 1),
  // 提供一个可选的曲线使动画感觉更流畅。
  curve: Curves.fastOutSlowIn,
)

3. 通过使用新属性重建来启动动画

#

最后,通过使用新属性重建 AnimatedContainer 来启动动画。如何触发重建?使用setState() 方法。

向应用添加一个按钮。当用户点击按钮时,在对 setState() 的调用中,使用新的宽度、高度、背景颜色和边框半径更新属性。

实际应用通常在固定值之间转换(例如,从灰色背景到绿色背景)。对于此应用,每次用户点击按钮时都会生成新值。

dart
FloatingActionButton(
  // 当用户点击按钮时
  onPressed: () {
    // 使用 setState 使用新值重建小部件。
    setState(() {
      // 创建一个随机数生成器。
      final random = Random();

      // 生成一个随机宽度和高度。
      _width = random.nextInt(300).toDouble();
      _height = random.nextInt(300).toDouble();

      // 生成一个随机颜色。
      _color = Color.fromRGBO(
        random.nextInt(256),
        random.nextInt(256),
        random.nextInt(256),
        1,
      );

      // 生成一个随机边框半径。
      _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> {
  // 定义具有默认值的各种属性。当用户点击 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(
            // 使用 State 类中存储的属性。
            width: _width,
            height: _height,
            decoration: BoxDecoration(
              color: _color,
              borderRadius: _borderRadius,
            ),
            // 定义动画应持续多长时间。
            duration: const Duration(seconds: 1),
            // 提供一个可选的曲线使动画感觉更流畅。
            curve: Curves.fastOutSlowIn,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          // 当用户点击按钮时
          onPressed: () {
            // 使用 setState 使用新值重建小部件。
            setState(() {
              // 创建一个随机数生成器。
              final random = Random();

              // 生成一个随机宽度和高度。
              _width = random.nextInt(300).toDouble();
              _height = random.nextInt(300).toDouble();

              // 生成一个随机颜色。
              _color = Color.fromRGBO(
                random.nextInt(256),
                random.nextInt(256),
                random.nextInt(256),
                1,
              );

              // 生成一个随机边框半径。
              _borderRadius =
                  BorderRadius.circular(random.nextInt(100).toDouble());
            });
          },
          child: const Icon(Icons.play_arrow),
        ),
      ),
    );
  }
}