跳到主要內容

為容器的屬性製作動畫

Container 類別提供了一種方便的方式來建立具有特定屬性的 Widget:寬度、高度、背景色彩、邊距、邊框等等。

簡單的動畫通常涉及隨著時間改變這些屬性。例如,您可能希望將背景顏色從灰色動畫到綠色,以指示使用者已選取某個項目。

為了動畫這些屬性,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> {
  // 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 來定義動畫應執行的時間長度。

dart
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() 的呼叫中更新屬性,使其具有新的寬度、高度、背景顏色和邊框圓角。

實際的應用程式通常會在固定值之間轉換(例如,從灰色背景到綠色背景)。對於這個應用程式,每次使用者點擊按鈕時都會產生新的值。

dart
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),
        ),
      ),
    );
  }
}